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