github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/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 for i := 0; i < t.NumField(); i++ { 431 if t.Field(i).PkgPath != "" { 432 return nil, StructuralError{"struct contains unexported fields"} 433 } 434 } 435 436 startingField := 0 437 438 n := t.NumField() 439 if n == 0 { 440 return bytesEncoder(nil), nil 441 } 442 443 // If the first element of the structure is a non-empty 444 // RawContents, then we don't bother serializing the rest. 445 if t.Field(0).Type == rawContentsType { 446 s := v.Field(0) 447 if s.Len() > 0 { 448 bytes := s.Bytes() 449 /* The RawContents will contain the tag and 450 * length fields but we'll also be writing 451 * those ourselves, so we strip them out of 452 * bytes */ 453 return bytesEncoder(stripTagAndLength(bytes)), nil 454 } 455 456 startingField = 1 457 } 458 459 switch n1 := n - startingField; n1 { 460 case 0: 461 return bytesEncoder(nil), nil 462 case 1: 463 return makeField(v.Field(startingField), parseFieldParameters(t.Field(startingField).Tag.Get("asn1"))) 464 default: 465 m := make([]encoder, n1) 466 for i := 0; i < n1; i++ { 467 m[i], err = makeField(v.Field(i+startingField), parseFieldParameters(t.Field(i+startingField).Tag.Get("asn1"))) 468 if err != nil { 469 return nil, err 470 } 471 } 472 473 return multiEncoder(m), nil 474 } 475 case reflect.Slice: 476 sliceType := v.Type() 477 if sliceType.Elem().Kind() == reflect.Uint8 { 478 return bytesEncoder(v.Bytes()), nil 479 } 480 481 var fp fieldParameters 482 483 switch l := v.Len(); l { 484 case 0: 485 return bytesEncoder(nil), nil 486 case 1: 487 return makeField(v.Index(0), fp) 488 default: 489 m := make([]encoder, l) 490 491 for i := 0; i < l; i++ { 492 m[i], err = makeField(v.Index(i), fp) 493 if err != nil { 494 return nil, err 495 } 496 } 497 498 return multiEncoder(m), nil 499 } 500 case reflect.String: 501 switch params.stringType { 502 case TagIA5String: 503 return makeIA5String(v.String()) 504 case TagPrintableString: 505 return makePrintableString(v.String()) 506 default: 507 return makeUTF8String(v.String()), nil 508 } 509 } 510 511 return nil, StructuralError{"unknown Go type"} 512 } 513 514 func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) { 515 if !v.IsValid() { 516 return nil, fmt.Errorf("asn1: cannot marshal nil value") 517 } 518 // If the field is an interface{} then recurse into it. 519 if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 { 520 return makeField(v.Elem(), params) 521 } 522 523 if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty { 524 return bytesEncoder(nil), nil 525 } 526 527 if params.optional && params.defaultValue != nil && canHaveDefaultValue(v.Kind()) { 528 defaultValue := reflect.New(v.Type()).Elem() 529 defaultValue.SetInt(*params.defaultValue) 530 531 if reflect.DeepEqual(v.Interface(), defaultValue.Interface()) { 532 return bytesEncoder(nil), nil 533 } 534 } 535 536 // If no default value is given then the zero value for the type is 537 // assumed to be the default value. This isn't obviously the correct 538 // behavior, but it's what Go has traditionally done. 539 if params.optional && params.defaultValue == nil { 540 if reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) { 541 return bytesEncoder(nil), nil 542 } 543 } 544 545 if v.Type() == rawValueType { 546 rv := v.Interface().(RawValue) 547 if len(rv.FullBytes) != 0 { 548 return bytesEncoder(rv.FullBytes), nil 549 } 550 551 t := new(taggedEncoder) 552 553 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})) 554 t.body = bytesEncoder(rv.Bytes) 555 556 return t, nil 557 } 558 559 tag, isCompound, ok := getUniversalType(v.Type()) 560 if !ok { 561 return nil, StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())} 562 } 563 class := ClassUniversal 564 565 if params.timeType != 0 && tag != TagUTCTime { 566 return nil, StructuralError{"explicit time type given to non-time member"} 567 } 568 569 if params.stringType != 0 && tag != TagPrintableString { 570 return nil, StructuralError{"explicit string type given to non-string member"} 571 } 572 573 switch tag { 574 case TagPrintableString: 575 if params.stringType == 0 { 576 // This is a string without an explicit string type. We'll use 577 // a PrintableString if the character set in the string is 578 // sufficiently limited, otherwise we'll use a UTF8String. 579 for _, r := range v.String() { 580 if r >= utf8.RuneSelf || !isPrintable(byte(r)) { 581 if !utf8.ValidString(v.String()) { 582 return nil, errors.New("asn1: string not valid UTF-8") 583 } 584 tag = TagUTF8String 585 break 586 } 587 } 588 } else { 589 tag = params.stringType 590 } 591 case TagUTCTime: 592 if params.timeType == TagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) { 593 tag = TagGeneralizedTime 594 } 595 } 596 597 if params.set { 598 if tag != TagSequence { 599 return nil, StructuralError{"non sequence tagged as set"} 600 } 601 tag = TagSet 602 } 603 604 t := new(taggedEncoder) 605 606 t.body, err = makeBody(v, params) 607 if err != nil { 608 return nil, err 609 } 610 611 bodyLen := t.body.Len() 612 613 if params.explicit { 614 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{class, tag, bodyLen, isCompound})) 615 616 tt := new(taggedEncoder) 617 618 tt.body = t 619 620 tt.tag = bytesEncoder(appendTagAndLength(tt.scratch[:0], tagAndLength{ 621 class: ClassContextSpecific, 622 tag: *params.tag, 623 length: bodyLen + t.tag.Len(), 624 isCompound: true, 625 })) 626 627 return tt, nil 628 } 629 630 if params.tag != nil { 631 // implicit tag. 632 tag = *params.tag 633 class = ClassContextSpecific 634 } 635 636 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{class, tag, bodyLen, isCompound})) 637 638 return t, nil 639 } 640 641 // Marshal returns the ASN.1 encoding of val. 642 // 643 // In addition to the struct tags recognised by Unmarshal, the following can be 644 // used: 645 // 646 // ia5: causes strings to be marshaled as ASN.1, IA5String values 647 // omitempty: causes empty slices to be skipped 648 // printable: causes strings to be marshaled as ASN.1, PrintableString values 649 // utf8: causes strings to be marshaled as ASN.1, UTF8String values 650 // utc: causes time.Time to be marshaled as ASN.1, UTCTime values 651 // generalized: causes time.Time to be marshaled as ASN.1, GeneralizedTime values 652 func Marshal(val interface{}) ([]byte, error) { 653 e, err := makeField(reflect.ValueOf(val), fieldParameters{}) 654 if err != nil { 655 return nil, err 656 } 657 b := make([]byte, e.Len()) 658 e.Encode(b) 659 return b, nil 660 }