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