github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/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 a 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 if !isPrintable(s[i]) { 272 return nil, StructuralError{"PrintableString contains invalid character"} 273 } 274 } 275 276 return stringEncoder(s), nil 277 } 278 279 func makeIA5String(s string) (e encoder, err error) { 280 for i := 0; i < len(s); i++ { 281 if s[i] > 127 { 282 return nil, StructuralError{"IA5String contains invalid character"} 283 } 284 } 285 286 return stringEncoder(s), nil 287 } 288 289 func makeUTF8String(s string) encoder { 290 return stringEncoder(s) 291 } 292 293 func appendTwoDigits(dst []byte, v int) []byte { 294 return append(dst, byte('0'+(v/10)%10), byte('0'+v%10)) 295 } 296 297 func appendFourDigits(dst []byte, v int) []byte { 298 var bytes [4]byte 299 for i := range bytes { 300 bytes[3-i] = '0' + byte(v%10) 301 v /= 10 302 } 303 return append(dst, bytes[:]...) 304 } 305 306 func outsideUTCRange(t time.Time) bool { 307 year := t.Year() 308 return year < 1950 || year >= 2050 309 } 310 311 func makeUTCTime(t time.Time) (e encoder, err error) { 312 dst := make([]byte, 0, 18) 313 314 dst, err = appendUTCTime(dst, t) 315 if err != nil { 316 return nil, err 317 } 318 319 return bytesEncoder(dst), nil 320 } 321 322 func makeGeneralizedTime(t time.Time) (e encoder, err error) { 323 dst := make([]byte, 0, 20) 324 325 dst, err = appendGeneralizedTime(dst, t) 326 if err != nil { 327 return nil, err 328 } 329 330 return bytesEncoder(dst), nil 331 } 332 333 func appendUTCTime(dst []byte, t time.Time) (ret []byte, err error) { 334 year := t.Year() 335 336 switch { 337 case 1950 <= year && year < 2000: 338 dst = appendTwoDigits(dst, year-1900) 339 case 2000 <= year && year < 2050: 340 dst = appendTwoDigits(dst, year-2000) 341 default: 342 return nil, StructuralError{"cannot represent time as UTCTime"} 343 } 344 345 return appendTimeCommon(dst, t), nil 346 } 347 348 func appendGeneralizedTime(dst []byte, t time.Time) (ret []byte, err error) { 349 year := t.Year() 350 if year < 0 || year > 9999 { 351 return nil, StructuralError{"cannot represent time as GeneralizedTime"} 352 } 353 354 dst = appendFourDigits(dst, year) 355 356 return appendTimeCommon(dst, t), nil 357 } 358 359 func appendTimeCommon(dst []byte, t time.Time) []byte { 360 _, month, day := t.Date() 361 362 dst = appendTwoDigits(dst, int(month)) 363 dst = appendTwoDigits(dst, day) 364 365 hour, min, sec := t.Clock() 366 367 dst = appendTwoDigits(dst, hour) 368 dst = appendTwoDigits(dst, min) 369 dst = appendTwoDigits(dst, sec) 370 371 _, offset := t.Zone() 372 373 switch { 374 case offset/60 == 0: 375 return append(dst, 'Z') 376 case offset > 0: 377 dst = append(dst, '+') 378 case offset < 0: 379 dst = append(dst, '-') 380 } 381 382 offsetMinutes := offset / 60 383 if offsetMinutes < 0 { 384 offsetMinutes = -offsetMinutes 385 } 386 387 dst = appendTwoDigits(dst, offsetMinutes/60) 388 dst = appendTwoDigits(dst, offsetMinutes%60) 389 390 return dst 391 } 392 393 func stripTagAndLength(in []byte) []byte { 394 _, offset, err := parseTagAndLength(in, 0) 395 if err != nil { 396 return in 397 } 398 return in[offset:] 399 } 400 401 func makeBody(value reflect.Value, params fieldParameters) (e encoder, err error) { 402 switch value.Type() { 403 case flagType: 404 return bytesEncoder(nil), nil 405 case timeType: 406 t := value.Interface().(time.Time) 407 if params.timeType == TagGeneralizedTime || outsideUTCRange(t) { 408 return makeGeneralizedTime(t) 409 } 410 return makeUTCTime(t) 411 case bitStringType: 412 return bitStringEncoder(value.Interface().(BitString)), nil 413 case objectIdentifierType: 414 return makeObjectIdentifier(value.Interface().(ObjectIdentifier)) 415 case bigIntType: 416 return makeBigInt(value.Interface().(*big.Int)) 417 } 418 419 switch v := value; v.Kind() { 420 case reflect.Bool: 421 if v.Bool() { 422 return byteFFEncoder, nil 423 } 424 return byte00Encoder, nil 425 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 426 return int64Encoder(v.Int()), nil 427 case reflect.Struct: 428 t := v.Type() 429 430 startingField := 0 431 432 n := t.NumField() 433 if n == 0 { 434 return bytesEncoder(nil), nil 435 } 436 437 // If the first element of the structure is a non-empty 438 // RawContents, then we don't bother serializing the rest. 439 if t.Field(0).Type == rawContentsType { 440 s := v.Field(0) 441 if s.Len() > 0 { 442 bytes := s.Bytes() 443 /* The RawContents will contain the tag and 444 * length fields but we'll also be writing 445 * those ourselves, so we strip them out of 446 * bytes */ 447 return bytesEncoder(stripTagAndLength(bytes)), nil 448 } 449 450 startingField = 1 451 } 452 453 switch n1 := n - startingField; n1 { 454 case 0: 455 return bytesEncoder(nil), nil 456 case 1: 457 return makeField(v.Field(startingField), parseFieldParameters(t.Field(startingField).Tag.Get("asn1"))) 458 default: 459 m := make([]encoder, n1) 460 for i := 0; i < n1; i++ { 461 m[i], err = makeField(v.Field(i+startingField), parseFieldParameters(t.Field(i+startingField).Tag.Get("asn1"))) 462 if err != nil { 463 return nil, err 464 } 465 } 466 467 return multiEncoder(m), nil 468 } 469 case reflect.Slice: 470 sliceType := v.Type() 471 if sliceType.Elem().Kind() == reflect.Uint8 { 472 return bytesEncoder(v.Bytes()), nil 473 } 474 475 var fp fieldParameters 476 477 switch l := v.Len(); l { 478 case 0: 479 return bytesEncoder(nil), nil 480 case 1: 481 return makeField(v.Index(0), fp) 482 default: 483 m := make([]encoder, l) 484 485 for i := 0; i < l; i++ { 486 m[i], err = makeField(v.Index(i), fp) 487 if err != nil { 488 return nil, err 489 } 490 } 491 492 return multiEncoder(m), nil 493 } 494 case reflect.String: 495 switch params.stringType { 496 case TagIA5String: 497 return makeIA5String(v.String()) 498 case TagPrintableString: 499 return makePrintableString(v.String()) 500 default: 501 return makeUTF8String(v.String()), nil 502 } 503 } 504 505 return nil, StructuralError{"unknown Go type"} 506 } 507 508 func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) { 509 if !v.IsValid() { 510 return nil, fmt.Errorf("asn1: cannot marshal nil value") 511 } 512 // If the field is an interface{} then recurse into it. 513 if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 { 514 return makeField(v.Elem(), params) 515 } 516 517 if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty { 518 return bytesEncoder(nil), nil 519 } 520 521 if params.optional && params.defaultValue != nil && canHaveDefaultValue(v.Kind()) { 522 defaultValue := reflect.New(v.Type()).Elem() 523 defaultValue.SetInt(*params.defaultValue) 524 525 if reflect.DeepEqual(v.Interface(), defaultValue.Interface()) { 526 return bytesEncoder(nil), nil 527 } 528 } 529 530 // If no default value is given then the zero value for the type is 531 // assumed to be the default value. This isn't obviously the correct 532 // behaviour, but it's what Go has traditionally done. 533 if params.optional && params.defaultValue == nil { 534 if reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) { 535 return bytesEncoder(nil), nil 536 } 537 } 538 539 if v.Type() == rawValueType { 540 rv := v.Interface().(RawValue) 541 if len(rv.FullBytes) != 0 { 542 return bytesEncoder(rv.FullBytes), nil 543 } 544 545 t := new(taggedEncoder) 546 547 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})) 548 t.body = bytesEncoder(rv.Bytes) 549 550 return t, nil 551 } 552 553 tag, isCompound, ok := getUniversalType(v.Type()) 554 if !ok { 555 return nil, StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())} 556 } 557 class := ClassUniversal 558 559 if params.timeType != 0 && tag != TagUTCTime { 560 return nil, StructuralError{"explicit time type given to non-time member"} 561 } 562 563 if params.stringType != 0 && tag != TagPrintableString { 564 return nil, StructuralError{"explicit string type given to non-string member"} 565 } 566 567 switch tag { 568 case TagPrintableString: 569 if params.stringType == 0 { 570 // This is a string without an explicit string type. We'll use 571 // a PrintableString if the character set in the string is 572 // sufficiently limited, otherwise we'll use a UTF8String. 573 for _, r := range v.String() { 574 if r >= utf8.RuneSelf || !isPrintable(byte(r)) { 575 if !utf8.ValidString(v.String()) { 576 return nil, errors.New("asn1: string not valid UTF-8") 577 } 578 tag = TagUTF8String 579 break 580 } 581 } 582 } else { 583 tag = params.stringType 584 } 585 case TagUTCTime: 586 if params.timeType == TagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) { 587 tag = TagGeneralizedTime 588 } 589 } 590 591 if params.set { 592 if tag != TagSequence { 593 return nil, StructuralError{"non sequence tagged as set"} 594 } 595 tag = TagSet 596 } 597 598 t := new(taggedEncoder) 599 600 t.body, err = makeBody(v, params) 601 if err != nil { 602 return nil, err 603 } 604 605 bodyLen := t.body.Len() 606 607 if params.explicit { 608 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{class, tag, bodyLen, isCompound})) 609 610 tt := new(taggedEncoder) 611 612 tt.body = t 613 614 tt.tag = bytesEncoder(appendTagAndLength(tt.scratch[:0], tagAndLength{ 615 class: ClassContextSpecific, 616 tag: *params.tag, 617 length: bodyLen + t.tag.Len(), 618 isCompound: true, 619 })) 620 621 return tt, nil 622 } 623 624 if params.tag != nil { 625 // implicit tag. 626 tag = *params.tag 627 class = ClassContextSpecific 628 } 629 630 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{class, tag, bodyLen, isCompound})) 631 632 return t, nil 633 } 634 635 // Marshal returns the ASN.1 encoding of val. 636 // 637 // In addition to the struct tags recognised by Unmarshal, the following can be 638 // used: 639 // 640 // ia5: causes strings to be marshaled as ASN.1, IA5 strings 641 // omitempty: causes empty slices to be skipped 642 // printable: causes strings to be marshaled as ASN.1, PrintableString strings. 643 // utf8: causes strings to be marshaled as ASN.1, UTF8 strings 644 func Marshal(val interface{}) ([]byte, error) { 645 e, err := makeField(reflect.ValueOf(val), fieldParameters{}) 646 if err != nil { 647 return nil, err 648 } 649 b := make([]byte, e.Len()) 650 e.Encode(b) 651 return b, nil 652 }