github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/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 "io" 12 "math/big" 13 "reflect" 14 "time" 15 "unicode/utf8" 16 ) 17 18 // A forkableWriter is an in-memory buffer that can be 19 // 'forked' to create new forkableWriters that bracket the 20 // original. After 21 // pre, post := w.fork(); 22 // the overall sequence of bytes represented is logically w+pre+post. 23 type forkableWriter struct { 24 *bytes.Buffer 25 pre, post *forkableWriter 26 } 27 28 func newForkableWriter() *forkableWriter { 29 return &forkableWriter{new(bytes.Buffer), nil, nil} 30 } 31 32 func (f *forkableWriter) fork() (pre, post *forkableWriter) { 33 if f.pre != nil || f.post != nil { 34 panic("have already forked") 35 } 36 f.pre = newForkableWriter() 37 f.post = newForkableWriter() 38 return f.pre, f.post 39 } 40 41 func (f *forkableWriter) Len() (l int) { 42 l += f.Buffer.Len() 43 if f.pre != nil { 44 l += f.pre.Len() 45 } 46 if f.post != nil { 47 l += f.post.Len() 48 } 49 return 50 } 51 52 func (f *forkableWriter) writeTo(out io.Writer) (n int, err error) { 53 n, err = out.Write(f.Bytes()) 54 if err != nil { 55 return 56 } 57 58 var nn int 59 60 if f.pre != nil { 61 nn, err = f.pre.writeTo(out) 62 n += nn 63 if err != nil { 64 return 65 } 66 } 67 68 if f.post != nil { 69 nn, err = f.post.writeTo(out) 70 n += nn 71 } 72 return 73 } 74 75 func marshalBase128Int(out *forkableWriter, n int64) (err error) { 76 if n == 0 { 77 err = out.WriteByte(0) 78 return 79 } 80 81 l := 0 82 for i := n; i > 0; i >>= 7 { 83 l++ 84 } 85 86 for i := l - 1; i >= 0; i-- { 87 o := byte(n >> uint(i*7)) 88 o &= 0x7f 89 if i != 0 { 90 o |= 0x80 91 } 92 err = out.WriteByte(o) 93 if err != nil { 94 return 95 } 96 } 97 98 return nil 99 } 100 101 func marshalInt64(out *forkableWriter, i int64) (err error) { 102 n := int64Length(i) 103 104 for ; n > 0; n-- { 105 err = out.WriteByte(byte(i >> uint((n-1)*8))) 106 if err != nil { 107 return 108 } 109 } 110 111 return nil 112 } 113 114 func int64Length(i int64) (numBytes int) { 115 numBytes = 1 116 117 for i > 127 { 118 numBytes++ 119 i >>= 8 120 } 121 122 for i < -128 { 123 numBytes++ 124 i >>= 8 125 } 126 127 return 128 } 129 130 func marshalBigInt(out *forkableWriter, n *big.Int) (err error) { 131 if n.Sign() < 0 { 132 // A negative number has to be converted to two's-complement 133 // form. So we'll subtract 1 and invert. If the 134 // most-significant-bit isn't set then we'll need to pad the 135 // beginning with 0xff in order to keep the number negative. 136 nMinus1 := new(big.Int).Neg(n) 137 nMinus1.Sub(nMinus1, bigOne) 138 bytes := nMinus1.Bytes() 139 for i := range bytes { 140 bytes[i] ^= 0xff 141 } 142 if len(bytes) == 0 || bytes[0]&0x80 == 0 { 143 err = out.WriteByte(0xff) 144 if err != nil { 145 return 146 } 147 } 148 _, err = out.Write(bytes) 149 } else if n.Sign() == 0 { 150 // Zero is written as a single 0 zero rather than no bytes. 151 err = out.WriteByte(0x00) 152 } else { 153 bytes := n.Bytes() 154 if len(bytes) > 0 && bytes[0]&0x80 != 0 { 155 // We'll have to pad this with 0x00 in order to stop it 156 // looking like a negative number. 157 err = out.WriteByte(0) 158 if err != nil { 159 return 160 } 161 } 162 _, err = out.Write(bytes) 163 } 164 return 165 } 166 167 func marshalLength(out *forkableWriter, i int) (err error) { 168 n := lengthLength(i) 169 170 for ; n > 0; n-- { 171 err = out.WriteByte(byte(i >> uint((n-1)*8))) 172 if err != nil { 173 return 174 } 175 } 176 177 return nil 178 } 179 180 func lengthLength(i int) (numBytes int) { 181 numBytes = 1 182 for i > 255 { 183 numBytes++ 184 i >>= 8 185 } 186 return 187 } 188 189 func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err error) { 190 b := uint8(t.class) << 6 191 if t.isCompound { 192 b |= 0x20 193 } 194 if t.tag >= 31 { 195 b |= 0x1f 196 err = out.WriteByte(b) 197 if err != nil { 198 return 199 } 200 err = marshalBase128Int(out, int64(t.tag)) 201 if err != nil { 202 return 203 } 204 } else { 205 b |= uint8(t.tag) 206 err = out.WriteByte(b) 207 if err != nil { 208 return 209 } 210 } 211 212 if t.length >= 128 { 213 l := lengthLength(t.length) 214 err = out.WriteByte(0x80 | byte(l)) 215 if err != nil { 216 return 217 } 218 err = marshalLength(out, t.length) 219 if err != nil { 220 return 221 } 222 } else { 223 err = out.WriteByte(byte(t.length)) 224 if err != nil { 225 return 226 } 227 } 228 229 return nil 230 } 231 232 func marshalBitString(out *forkableWriter, b BitString) (err error) { 233 paddingBits := byte((8 - b.BitLength%8) % 8) 234 err = out.WriteByte(paddingBits) 235 if err != nil { 236 return 237 } 238 _, err = out.Write(b.Bytes) 239 return 240 } 241 242 func marshalObjectIdentifier(out *forkableWriter, oid []int) (err error) { 243 if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) { 244 return StructuralError{"invalid object identifier"} 245 } 246 247 err = marshalBase128Int(out, int64(oid[0]*40+oid[1])) 248 if err != nil { 249 return 250 } 251 for i := 2; i < len(oid); i++ { 252 err = marshalBase128Int(out, int64(oid[i])) 253 if err != nil { 254 return 255 } 256 } 257 258 return 259 } 260 261 func marshalPrintableString(out *forkableWriter, s string) (err error) { 262 b := []byte(s) 263 for _, c := range b { 264 if !isPrintable(c) { 265 return StructuralError{"PrintableString contains invalid character"} 266 } 267 } 268 269 _, err = out.Write(b) 270 return 271 } 272 273 func marshalIA5String(out *forkableWriter, s string) (err error) { 274 b := []byte(s) 275 for _, c := range b { 276 if c > 127 { 277 return StructuralError{"IA5String contains invalid character"} 278 } 279 } 280 281 _, err = out.Write(b) 282 return 283 } 284 285 func marshalUTF8String(out *forkableWriter, s string) (err error) { 286 _, err = out.Write([]byte(s)) 287 return 288 } 289 290 func marshalTwoDigits(out *forkableWriter, v int) (err error) { 291 err = out.WriteByte(byte('0' + (v/10)%10)) 292 if err != nil { 293 return 294 } 295 return out.WriteByte(byte('0' + v%10)) 296 } 297 298 func marshalUTCTime(out *forkableWriter, t time.Time) (err error) { 299 year, month, day := t.Date() 300 301 switch { 302 case 1950 <= year && year < 2000: 303 err = marshalTwoDigits(out, int(year-1900)) 304 case 2000 <= year && year < 2050: 305 err = marshalTwoDigits(out, int(year-2000)) 306 default: 307 return StructuralError{"cannot represent time as UTCTime"} 308 } 309 if err != nil { 310 return 311 } 312 313 err = marshalTwoDigits(out, int(month)) 314 if err != nil { 315 return 316 } 317 318 err = marshalTwoDigits(out, day) 319 if err != nil { 320 return 321 } 322 323 hour, min, sec := t.Clock() 324 325 err = marshalTwoDigits(out, hour) 326 if err != nil { 327 return 328 } 329 330 err = marshalTwoDigits(out, min) 331 if err != nil { 332 return 333 } 334 335 err = marshalTwoDigits(out, sec) 336 if err != nil { 337 return 338 } 339 340 _, offset := t.Zone() 341 342 switch { 343 case offset/60 == 0: 344 err = out.WriteByte('Z') 345 return 346 case offset > 0: 347 err = out.WriteByte('+') 348 case offset < 0: 349 err = out.WriteByte('-') 350 } 351 352 if err != nil { 353 return 354 } 355 356 offsetMinutes := offset / 60 357 if offsetMinutes < 0 { 358 offsetMinutes = -offsetMinutes 359 } 360 361 err = marshalTwoDigits(out, offsetMinutes/60) 362 if err != nil { 363 return 364 } 365 366 err = marshalTwoDigits(out, offsetMinutes%60) 367 return 368 } 369 370 func stripTagAndLength(in []byte) []byte { 371 _, offset, err := parseTagAndLength(in, 0) 372 if err != nil { 373 return in 374 } 375 return in[offset:] 376 } 377 378 func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err error) { 379 switch value.Type() { 380 case timeType: 381 return marshalUTCTime(out, value.Interface().(time.Time)) 382 case bitStringType: 383 return marshalBitString(out, value.Interface().(BitString)) 384 case objectIdentifierType: 385 return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier)) 386 case bigIntType: 387 return marshalBigInt(out, value.Interface().(*big.Int)) 388 } 389 390 switch v := value; v.Kind() { 391 case reflect.Bool: 392 if v.Bool() { 393 return out.WriteByte(255) 394 } else { 395 return out.WriteByte(0) 396 } 397 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 398 return marshalInt64(out, int64(v.Int())) 399 case reflect.Struct: 400 t := v.Type() 401 402 startingField := 0 403 404 // If the first element of the structure is a non-empty 405 // RawContents, then we don't bother serializing the rest. 406 if t.NumField() > 0 && t.Field(0).Type == rawContentsType { 407 s := v.Field(0) 408 if s.Len() > 0 { 409 bytes := make([]byte, s.Len()) 410 for i := 0; i < s.Len(); i++ { 411 bytes[i] = uint8(s.Index(i).Uint()) 412 } 413 /* The RawContents will contain the tag and 414 * length fields but we'll also be writing 415 * those ourselves, so we strip them out of 416 * bytes */ 417 _, err = out.Write(stripTagAndLength(bytes)) 418 return 419 } else { 420 startingField = 1 421 } 422 } 423 424 for i := startingField; i < t.NumField(); i++ { 425 var pre *forkableWriter 426 pre, out = out.fork() 427 err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag.Get("asn1"))) 428 if err != nil { 429 return 430 } 431 } 432 return 433 case reflect.Slice: 434 sliceType := v.Type() 435 if sliceType.Elem().Kind() == reflect.Uint8 { 436 bytes := make([]byte, v.Len()) 437 for i := 0; i < v.Len(); i++ { 438 bytes[i] = uint8(v.Index(i).Uint()) 439 } 440 _, err = out.Write(bytes) 441 return 442 } 443 444 var fp fieldParameters 445 for i := 0; i < v.Len(); i++ { 446 var pre *forkableWriter 447 pre, out = out.fork() 448 err = marshalField(pre, v.Index(i), fp) 449 if err != nil { 450 return 451 } 452 } 453 return 454 case reflect.String: 455 switch params.stringType { 456 case tagIA5String: 457 return marshalIA5String(out, v.String()) 458 case tagPrintableString: 459 return marshalPrintableString(out, v.String()) 460 default: 461 return marshalUTF8String(out, v.String()) 462 } 463 } 464 465 return StructuralError{"unknown Go type"} 466 } 467 468 func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err error) { 469 // If the field is an interface{} then recurse into it. 470 if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 { 471 return marshalField(out, v.Elem(), params) 472 } 473 474 if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty { 475 return 476 } 477 478 if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) { 479 return 480 } 481 482 if v.Type() == rawValueType { 483 rv := v.Interface().(RawValue) 484 if len(rv.FullBytes) != 0 { 485 _, err = out.Write(rv.FullBytes) 486 } else { 487 err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound}) 488 if err != nil { 489 return 490 } 491 _, err = out.Write(rv.Bytes) 492 } 493 return 494 } 495 496 tag, isCompound, ok := getUniversalType(v.Type()) 497 if !ok { 498 err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())} 499 return 500 } 501 class := classUniversal 502 503 if params.stringType != 0 && tag != tagPrintableString { 504 return StructuralError{"explicit string type given to non-string member"} 505 } 506 507 if tag == tagPrintableString { 508 if params.stringType == 0 { 509 // This is a string without an explicit string type. We'll use 510 // a PrintableString if the character set in the string is 511 // sufficiently limited, otherwise we'll use a UTF8String. 512 for _, r := range v.String() { 513 if r >= utf8.RuneSelf || !isPrintable(byte(r)) { 514 if !utf8.ValidString(v.String()) { 515 return errors.New("asn1: string not valid UTF-8") 516 } 517 tag = tagUTF8String 518 break 519 } 520 } 521 } else { 522 tag = params.stringType 523 } 524 } 525 526 if params.set { 527 if tag != tagSequence { 528 return StructuralError{"non sequence tagged as set"} 529 } 530 tag = tagSet 531 } 532 533 tags, body := out.fork() 534 535 err = marshalBody(body, v, params) 536 if err != nil { 537 return 538 } 539 540 bodyLen := body.Len() 541 542 var explicitTag *forkableWriter 543 if params.explicit { 544 explicitTag, tags = tags.fork() 545 } 546 547 if !params.explicit && params.tag != nil { 548 // implicit tag. 549 tag = *params.tag 550 class = classContextSpecific 551 } 552 553 err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound}) 554 if err != nil { 555 return 556 } 557 558 if params.explicit { 559 err = marshalTagAndLength(explicitTag, tagAndLength{ 560 class: classContextSpecific, 561 tag: *params.tag, 562 length: bodyLen + tags.Len(), 563 isCompound: true, 564 }) 565 } 566 567 return nil 568 } 569 570 // Marshal returns the ASN.1 encoding of val. 571 func Marshal(val interface{}) ([]byte, error) { 572 var out bytes.Buffer 573 v := reflect.ValueOf(val) 574 f := newForkableWriter() 575 err := marshalField(f, v, fieldParameters{}) 576 if err != nil { 577 return nil, err 578 } 579 _, err = f.writeTo(&out) 580 return out.Bytes(), nil 581 }