github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/src/encoding/asn1/marshal.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package asn1 6 7 import ( 8 "errors" 9 "fmt" 10 "math/big" 11 "reflect" 12 "time" 13 "unicode/utf8" 14 ) 15 16 var ( 17 byte00Encoder encoder = byteEncoder(0x00) 18 byteFFEncoder encoder = byteEncoder(0xff) 19 ) 20 21 // encoder represents an ASN.1 element that is waiting to be marshaled. 22 type encoder interface { 23 // Len returns the number of bytes needed to marshal this element. 24 Len() int 25 // Encode encodes this element by writing Len() bytes to dst. 26 Encode(dst []byte) 27 } 28 29 type byteEncoder byte 30 31 func (c byteEncoder) Len() int { 32 return 1 33 } 34 35 func (c byteEncoder) Encode(dst []byte) { 36 dst[0] = byte(c) 37 } 38 39 type bytesEncoder []byte 40 41 func (b bytesEncoder) Len() int { 42 return len(b) 43 } 44 45 func (b bytesEncoder) Encode(dst []byte) { 46 if copy(dst, b) != len(b) { 47 panic("internal error") 48 } 49 } 50 51 type stringEncoder string 52 53 func (s stringEncoder) Len() int { 54 return len(s) 55 } 56 57 func (s stringEncoder) Encode(dst []byte) { 58 if copy(dst, s) != len(s) { 59 panic("internal error") 60 } 61 } 62 63 type multiEncoder []encoder 64 65 func (m multiEncoder) Len() int { 66 var size int 67 for _, e := range m { 68 size += e.Len() 69 } 70 return size 71 } 72 73 func (m multiEncoder) Encode(dst []byte) { 74 var off int 75 for _, e := range m { 76 e.Encode(dst[off:]) 77 off += e.Len() 78 } 79 } 80 81 type taggedEncoder struct { 82 // scratch contains temporary space for encoding the tag and length of 83 // an element in order to avoid extra allocations. 84 scratch [8]byte 85 tag encoder 86 body encoder 87 } 88 89 func (t *taggedEncoder) Len() int { 90 return t.tag.Len() + t.body.Len() 91 } 92 93 func (t *taggedEncoder) Encode(dst []byte) { 94 t.tag.Encode(dst) 95 t.body.Encode(dst[t.tag.Len():]) 96 } 97 98 type int64Encoder int64 99 100 func (i int64Encoder) Len() int { 101 n := 1 102 103 for i > 127 { 104 n++ 105 i >>= 8 106 } 107 108 for i < -128 { 109 n++ 110 i >>= 8 111 } 112 113 return n 114 } 115 116 func (i int64Encoder) Encode(dst []byte) { 117 n := i.Len() 118 119 for j := 0; j < n; j++ { 120 dst[j] = byte(i >> uint((n-1-j)*8)) 121 } 122 } 123 124 func base128IntLength(n int64) int { 125 if n == 0 { 126 return 1 127 } 128 129 l := 0 130 for i := n; i > 0; i >>= 7 { 131 l++ 132 } 133 134 return l 135 } 136 137 func appendBase128Int(dst []byte, n int64) []byte { 138 l := base128IntLength(n) 139 140 for i := l - 1; i >= 0; i-- { 141 o := byte(n >> uint(i*7)) 142 o &= 0x7f 143 if i != 0 { 144 o |= 0x80 145 } 146 147 dst = append(dst, o) 148 } 149 150 return dst 151 } 152 153 func makeBigInt(n *big.Int) (encoder, error) { 154 if n == nil { 155 return nil, StructuralError{"empty integer"} 156 } 157 158 if n.Sign() < 0 { 159 // A negative number has to be converted to two's-complement 160 // form. So we'll invert and subtract 1. If the 161 // most-significant-bit isn't set then we'll need to pad the 162 // beginning with 0xff in order to keep the number negative. 163 nMinus1 := new(big.Int).Neg(n) 164 nMinus1.Sub(nMinus1, bigOne) 165 bytes := nMinus1.Bytes() 166 for i := range bytes { 167 bytes[i] ^= 0xff 168 } 169 if len(bytes) == 0 || bytes[0]&0x80 == 0 { 170 return multiEncoder([]encoder{byteFFEncoder, bytesEncoder(bytes)}), nil 171 } 172 return bytesEncoder(bytes), nil 173 } else if n.Sign() == 0 { 174 // Zero is written as a single 0 zero rather than no bytes. 175 return byte00Encoder, nil 176 } else { 177 bytes := n.Bytes() 178 if len(bytes) > 0 && bytes[0]&0x80 != 0 { 179 // We'll have to pad this with 0x00 in order to stop it 180 // looking like a negative number. 181 return multiEncoder([]encoder{byte00Encoder, bytesEncoder(bytes)}), nil 182 } 183 return bytesEncoder(bytes), nil 184 } 185 } 186 187 func appendLength(dst []byte, i int) []byte { 188 n := lengthLength(i) 189 190 for ; n > 0; n-- { 191 dst = append(dst, byte(i>>uint((n-1)*8))) 192 } 193 194 return dst 195 } 196 197 func lengthLength(i int) (numBytes int) { 198 numBytes = 1 199 for i > 255 { 200 numBytes++ 201 i >>= 8 202 } 203 return 204 } 205 206 func appendTagAndLength(dst []byte, t tagAndLength) []byte { 207 b := uint8(t.class) << 6 208 if t.isCompound { 209 b |= 0x20 210 } 211 if t.tag >= 31 { 212 b |= 0x1f 213 dst = append(dst, b) 214 dst = appendBase128Int(dst, int64(t.tag)) 215 } else { 216 b |= uint8(t.tag) 217 dst = append(dst, b) 218 } 219 220 if t.length >= 128 { 221 l := lengthLength(t.length) 222 dst = append(dst, 0x80|byte(l)) 223 dst = appendLength(dst, t.length) 224 } else { 225 dst = append(dst, byte(t.length)) 226 } 227 228 return dst 229 } 230 231 type bitStringEncoder BitString 232 233 func (b bitStringEncoder) Len() int { 234 return len(b.Bytes) + 1 235 } 236 237 func (b bitStringEncoder) Encode(dst []byte) { 238 dst[0] = byte((8 - b.BitLength%8) % 8) 239 if copy(dst[1:], b.Bytes) != len(b.Bytes) { 240 panic("internal error") 241 } 242 } 243 244 type oidEncoder []int 245 246 func (oid oidEncoder) Len() int { 247 l := base128IntLength(int64(oid[0]*40 + oid[1])) 248 for i := 2; i < len(oid); i++ { 249 l += base128IntLength(int64(oid[i])) 250 } 251 return l 252 } 253 254 func (oid oidEncoder) Encode(dst []byte) { 255 dst = appendBase128Int(dst[:0], int64(oid[0]*40+oid[1])) 256 for i := 2; i < len(oid); i++ { 257 dst = appendBase128Int(dst, int64(oid[i])) 258 } 259 } 260 261 func makeObjectIdentifier(oid []int) (e encoder, err error) { 262 if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) { 263 return nil, StructuralError{"invalid object identifier"} 264 } 265 266 return oidEncoder(oid), nil 267 } 268 269 func makePrintableString(s string) (e encoder, err error) { 270 for i := 0; i < len(s); i++ { 271 // The asterisk is often used in PrintableString, even though 272 // it is invalid. If a PrintableString was specifically 273 // requested then the asterisk is permitted by this code. 274 if !isPrintable(s[i], allowAsterisk) { 275 return nil, StructuralError{"PrintableString contains invalid character"} 276 } 277 } 278 279 return stringEncoder(s), nil 280 } 281 282 func makeIA5String(s string) (e encoder, err error) { 283 for i := 0; i < len(s); i++ { 284 if s[i] > 127 { 285 return nil, StructuralError{"IA5String contains invalid character"} 286 } 287 } 288 289 return stringEncoder(s), nil 290 } 291 292 func makeUTF8String(s string) encoder { 293 return stringEncoder(s) 294 } 295 296 func appendTwoDigits(dst []byte, v int) []byte { 297 return append(dst, byte('0'+(v/10)%10), byte('0'+v%10)) 298 } 299 300 func appendFourDigits(dst []byte, v int) []byte { 301 var bytes [4]byte 302 for i := range bytes { 303 bytes[3-i] = '0' + byte(v%10) 304 v /= 10 305 } 306 return append(dst, bytes[:]...) 307 } 308 309 func outsideUTCRange(t time.Time) bool { 310 year := t.Year() 311 return year < 1950 || year >= 2050 312 } 313 314 func makeUTCTime(t time.Time) (e encoder, err error) { 315 dst := make([]byte, 0, 18) 316 317 dst, err = appendUTCTime(dst, t) 318 if err != nil { 319 return nil, err 320 } 321 322 return bytesEncoder(dst), nil 323 } 324 325 func makeGeneralizedTime(t time.Time) (e encoder, err error) { 326 dst := make([]byte, 0, 20) 327 328 dst, err = appendGeneralizedTime(dst, t) 329 if err != nil { 330 return nil, err 331 } 332 333 return bytesEncoder(dst), nil 334 } 335 336 func appendUTCTime(dst []byte, t time.Time) (ret []byte, err error) { 337 year := t.Year() 338 339 switch { 340 case 1950 <= year && year < 2000: 341 dst = appendTwoDigits(dst, year-1900) 342 case 2000 <= year && year < 2050: 343 dst = appendTwoDigits(dst, year-2000) 344 default: 345 return nil, StructuralError{"cannot represent time as UTCTime"} 346 } 347 348 return appendTimeCommon(dst, t), nil 349 } 350 351 func appendGeneralizedTime(dst []byte, t time.Time) (ret []byte, err error) { 352 year := t.Year() 353 if year < 0 || year > 9999 { 354 return nil, StructuralError{"cannot represent time as GeneralizedTime"} 355 } 356 357 dst = appendFourDigits(dst, year) 358 359 return appendTimeCommon(dst, t), nil 360 } 361 362 func appendTimeCommon(dst []byte, t time.Time) []byte { 363 _, month, day := t.Date() 364 365 dst = appendTwoDigits(dst, int(month)) 366 dst = appendTwoDigits(dst, day) 367 368 hour, min, sec := t.Clock() 369 370 dst = appendTwoDigits(dst, hour) 371 dst = appendTwoDigits(dst, min) 372 dst = appendTwoDigits(dst, sec) 373 374 _, offset := t.Zone() 375 376 switch { 377 case offset/60 == 0: 378 return append(dst, 'Z') 379 case offset > 0: 380 dst = append(dst, '+') 381 case offset < 0: 382 dst = append(dst, '-') 383 } 384 385 offsetMinutes := offset / 60 386 if offsetMinutes < 0 { 387 offsetMinutes = -offsetMinutes 388 } 389 390 dst = appendTwoDigits(dst, offsetMinutes/60) 391 dst = appendTwoDigits(dst, offsetMinutes%60) 392 393 return dst 394 } 395 396 func stripTagAndLength(in []byte) []byte { 397 _, offset, err := parseTagAndLength(in, 0) 398 if err != nil { 399 return in 400 } 401 return in[offset:] 402 } 403 404 func makeBody(value reflect.Value, params fieldParameters) (e encoder, err error) { 405 switch value.Type() { 406 case flagType: 407 return bytesEncoder(nil), nil 408 case timeType: 409 t := value.Interface().(time.Time) 410 if params.timeType == TagGeneralizedTime || outsideUTCRange(t) { 411 return makeGeneralizedTime(t) 412 } 413 return makeUTCTime(t) 414 case bitStringType: 415 return bitStringEncoder(value.Interface().(BitString)), nil 416 case objectIdentifierType: 417 return makeObjectIdentifier(value.Interface().(ObjectIdentifier)) 418 case bigIntType: 419 return makeBigInt(value.Interface().(*big.Int)) 420 } 421 422 switch v := value; v.Kind() { 423 case reflect.Bool: 424 if v.Bool() { 425 return byteFFEncoder, nil 426 } 427 return byte00Encoder, nil 428 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 429 return int64Encoder(v.Int()), nil 430 case reflect.Struct: 431 t := v.Type() 432 433 for i := 0; i < t.NumField(); i++ { 434 if t.Field(i).PkgPath != "" { 435 return nil, StructuralError{"struct contains unexported fields"} 436 } 437 } 438 439 startingField := 0 440 441 n := t.NumField() 442 if n == 0 { 443 return bytesEncoder(nil), nil 444 } 445 446 // If the first element of the structure is a non-empty 447 // RawContents, then we don't bother serializing the rest. 448 if t.Field(0).Type == rawContentsType { 449 s := v.Field(0) 450 if s.Len() > 0 { 451 bytes := s.Bytes() 452 /* The RawContents will contain the tag and 453 * length fields but we'll also be writing 454 * those ourselves, so we strip them out of 455 * bytes */ 456 return bytesEncoder(stripTagAndLength(bytes)), nil 457 } 458 459 startingField = 1 460 } 461 462 switch n1 := n - startingField; n1 { 463 case 0: 464 return bytesEncoder(nil), nil 465 case 1: 466 return makeField(v.Field(startingField), parseFieldParameters(t.Field(startingField).Tag.Get("asn1"))) 467 default: 468 m := make([]encoder, n1) 469 for i := 0; i < n1; i++ { 470 m[i], err = makeField(v.Field(i+startingField), parseFieldParameters(t.Field(i+startingField).Tag.Get("asn1"))) 471 if err != nil { 472 return nil, err 473 } 474 } 475 476 return multiEncoder(m), nil 477 } 478 case reflect.Slice: 479 sliceType := v.Type() 480 if sliceType.Elem().Kind() == reflect.Uint8 { 481 return bytesEncoder(v.Bytes()), nil 482 } 483 484 var fp fieldParameters 485 486 switch l := v.Len(); l { 487 case 0: 488 return bytesEncoder(nil), nil 489 case 1: 490 return makeField(v.Index(0), fp) 491 default: 492 m := make([]encoder, l) 493 494 for i := 0; i < l; i++ { 495 m[i], err = makeField(v.Index(i), fp) 496 if err != nil { 497 return nil, err 498 } 499 } 500 501 return multiEncoder(m), nil 502 } 503 case reflect.String: 504 switch params.stringType { 505 case TagIA5String: 506 return makeIA5String(v.String()) 507 case TagPrintableString: 508 return makePrintableString(v.String()) 509 default: 510 return makeUTF8String(v.String()), nil 511 } 512 } 513 514 return nil, StructuralError{"unknown Go type"} 515 } 516 517 func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) { 518 if !v.IsValid() { 519 return nil, fmt.Errorf("asn1: cannot marshal nil value") 520 } 521 // If the field is an interface{} then recurse into it. 522 if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 { 523 return makeField(v.Elem(), params) 524 } 525 526 if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty { 527 return bytesEncoder(nil), nil 528 } 529 530 if params.optional && params.defaultValue != nil && canHaveDefaultValue(v.Kind()) { 531 defaultValue := reflect.New(v.Type()).Elem() 532 defaultValue.SetInt(*params.defaultValue) 533 534 if reflect.DeepEqual(v.Interface(), defaultValue.Interface()) { 535 return bytesEncoder(nil), nil 536 } 537 } 538 539 // If no default value is given then the zero value for the type is 540 // assumed to be the default value. This isn't obviously the correct 541 // behavior, but it's what Go has traditionally done. 542 if params.optional && params.defaultValue == nil { 543 if reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) { 544 return bytesEncoder(nil), nil 545 } 546 } 547 548 if v.Type() == rawValueType { 549 rv := v.Interface().(RawValue) 550 if len(rv.FullBytes) != 0 { 551 return bytesEncoder(rv.FullBytes), nil 552 } 553 554 t := new(taggedEncoder) 555 556 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})) 557 t.body = bytesEncoder(rv.Bytes) 558 559 return t, nil 560 } 561 562 matchAny, tag, isCompound, ok := getUniversalType(v.Type()) 563 if !ok || matchAny { 564 return nil, StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())} 565 } 566 567 if params.timeType != 0 && tag != TagUTCTime { 568 return nil, StructuralError{"explicit time type given to non-time member"} 569 } 570 571 if params.stringType != 0 && tag != TagPrintableString { 572 return nil, StructuralError{"explicit string type given to non-string member"} 573 } 574 575 switch tag { 576 case TagPrintableString: 577 if params.stringType == 0 { 578 // This is a string without an explicit string type. We'll use 579 // a PrintableString if the character set in the string is 580 // sufficiently limited, otherwise we'll use a UTF8String. 581 for _, r := range v.String() { 582 if r >= utf8.RuneSelf || !isPrintable(byte(r), rejectAsterisk) { 583 if !utf8.ValidString(v.String()) { 584 return nil, errors.New("asn1: string not valid UTF-8") 585 } 586 tag = TagUTF8String 587 break 588 } 589 } 590 } else { 591 tag = params.stringType 592 } 593 case TagUTCTime: 594 if params.timeType == TagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) { 595 tag = TagGeneralizedTime 596 } 597 } 598 599 if params.set { 600 if tag != TagSequence { 601 return nil, StructuralError{"non sequence tagged as set"} 602 } 603 tag = TagSet 604 } 605 606 t := new(taggedEncoder) 607 608 t.body, err = makeBody(v, params) 609 if err != nil { 610 return nil, err 611 } 612 613 bodyLen := t.body.Len() 614 615 class := ClassUniversal 616 if params.tag != nil { 617 if params.application { 618 class = ClassApplication 619 } else { 620 class = ClassContextSpecific 621 } 622 623 if params.explicit { 624 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{ClassUniversal, tag, bodyLen, isCompound})) 625 626 tt := new(taggedEncoder) 627 628 tt.body = t 629 630 tt.tag = bytesEncoder(appendTagAndLength(tt.scratch[:0], tagAndLength{ 631 class: class, 632 tag: *params.tag, 633 length: bodyLen + t.tag.Len(), 634 isCompound: true, 635 })) 636 637 return tt, nil 638 } 639 640 // implicit tag. 641 tag = *params.tag 642 } 643 644 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{class, tag, bodyLen, isCompound})) 645 646 return t, nil 647 } 648 649 // Marshal returns the ASN.1 encoding of val. 650 // 651 // In addition to the struct tags recognised by Unmarshal, the following can be 652 // used: 653 // 654 // ia5: causes strings to be marshaled as ASN.1, IA5String values 655 // omitempty: causes empty slices to be skipped 656 // printable: causes strings to be marshaled as ASN.1, PrintableString values 657 // utf8: causes strings to be marshaled as ASN.1, UTF8String values 658 // utc: causes time.Time to be marshaled as ASN.1, UTCTime values 659 // generalized: causes time.Time to be marshaled as ASN.1, GeneralizedTime values 660 func Marshal(val interface{}) ([]byte, error) { 661 e, err := makeField(reflect.ValueOf(val), fieldParameters{}) 662 if err != nil { 663 return nil, err 664 } 665 b := make([]byte, e.Len()) 666 e.Encode(b) 667 return b, nil 668 }