github.phpd.cn/hashicorp/packer@v1.3.2/builder/azure/pkcs12/pkcs12.go (about) 1 // Copyright 2015 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 pkcs12 implements some of PKCS#12. 6 // 7 // This implementation is distilled from https://tools.ietf.org/html/rfc7292 8 // and referenced documents. It is intended for decoding P12/PFX-stored 9 // certificates and keys for use with the crypto/tls package. 10 package pkcs12 11 12 import ( 13 "crypto/ecdsa" 14 "crypto/rand" 15 "crypto/rsa" 16 "crypto/x509" 17 "crypto/x509/pkix" 18 "encoding/asn1" 19 "encoding/hex" 20 "encoding/pem" 21 "errors" 22 "io" 23 ) 24 25 var ( 26 oidDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 1}) 27 oidEncryptedDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 6}) 28 29 oidFriendlyName = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 20}) 30 oidLocalKeyID = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 21}) 31 oidMicrosoftCSPName = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 4, 1, 311, 17, 1}) 32 33 localKeyId = []byte{0x01, 0x00, 0x00, 0x00} 34 ) 35 36 type pfxPdu struct { 37 Version int 38 AuthSafe contentInfo 39 MacData macData `asn1:"optional"` 40 } 41 42 type contentInfo struct { 43 ContentType asn1.ObjectIdentifier 44 Content asn1.RawValue `asn1:"tag:0,explicit,optional"` 45 } 46 47 type encryptedData struct { 48 Version int 49 EncryptedContentInfo encryptedContentInfo 50 } 51 52 type encryptedContentInfo struct { 53 ContentType asn1.ObjectIdentifier 54 ContentEncryptionAlgorithm pkix.AlgorithmIdentifier 55 EncryptedContent []byte `asn1:"tag:0,optional"` 56 } 57 58 func (i encryptedContentInfo) Algorithm() pkix.AlgorithmIdentifier { 59 return i.ContentEncryptionAlgorithm 60 } 61 62 func (i encryptedContentInfo) Data() []byte { return i.EncryptedContent } 63 64 type safeBag struct { 65 Id asn1.ObjectIdentifier 66 Value asn1.RawValue `asn1:"tag:0,explicit"` 67 Attributes []pkcs12Attribute `asn1:"set,optional"` 68 } 69 70 type pkcs12Attribute struct { 71 Id asn1.ObjectIdentifier 72 Value asn1.RawValue `asn1:"set"` 73 } 74 75 type encryptedPrivateKeyInfo struct { 76 AlgorithmIdentifier pkix.AlgorithmIdentifier 77 EncryptedData []byte 78 } 79 80 func (i encryptedPrivateKeyInfo) Algorithm() pkix.AlgorithmIdentifier { 81 return i.AlgorithmIdentifier 82 } 83 84 func (i encryptedPrivateKeyInfo) Data() []byte { 85 return i.EncryptedData 86 } 87 88 // PEM block types 89 const ( 90 certificateType = "CERTIFICATE" 91 privateKeyType = "PRIVATE KEY" 92 ) 93 94 // unmarshal calls asn1.Unmarshal, but also returns an error if there is any 95 // trailing data after unmarshalling. 96 func unmarshal(in []byte, out interface{}) error { 97 trailing, err := asn1.Unmarshal(in, out) 98 if err != nil { 99 return err 100 } 101 if len(trailing) != 0 { 102 return errors.New("pkcs12: trailing data found") 103 } 104 return nil 105 } 106 107 // ConvertToPEM converts all "safe bags" contained in pfxData to PEM blocks. 108 func ToPEM(pfxData []byte, password string) ([]*pem.Block, error) { 109 encodedPassword, err := bmpString(password) 110 if err != nil { 111 return nil, ErrIncorrectPassword 112 } 113 114 bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword) 115 116 blocks := make([]*pem.Block, 0, len(bags)) 117 for _, bag := range bags { 118 block, err := convertBag(&bag, encodedPassword) 119 if err != nil { 120 return nil, err 121 } 122 blocks = append(blocks, block) 123 } 124 125 return blocks, nil 126 } 127 128 func convertBag(bag *safeBag, password []byte) (*pem.Block, error) { 129 block := &pem.Block{ 130 Headers: make(map[string]string), 131 } 132 133 for _, attribute := range bag.Attributes { 134 k, v, err := convertAttribute(&attribute) 135 if err != nil { 136 return nil, err 137 } 138 block.Headers[k] = v 139 } 140 141 switch { 142 case bag.Id.Equal(oidCertBag): 143 block.Type = certificateType 144 certsData, err := decodeCertBag(bag.Value.Bytes) 145 if err != nil { 146 return nil, err 147 } 148 block.Bytes = certsData 149 case bag.Id.Equal(oidPKCS8ShroudedKeyBag): 150 block.Type = privateKeyType 151 152 key, err := decodePkcs8ShroudedKeyBag(bag.Value.Bytes, password) 153 if err != nil { 154 return nil, err 155 } 156 157 switch key := key.(type) { 158 case *rsa.PrivateKey: 159 block.Bytes = x509.MarshalPKCS1PrivateKey(key) 160 case *ecdsa.PrivateKey: 161 block.Bytes, err = x509.MarshalECPrivateKey(key) 162 if err != nil { 163 return nil, err 164 } 165 default: 166 return nil, errors.New("found unknown private key type in PKCS#8 wrapping") 167 } 168 default: 169 return nil, errors.New("don't know how to convert a safe bag of type " + bag.Id.String()) 170 } 171 return block, nil 172 } 173 174 func convertAttribute(attribute *pkcs12Attribute) (key, value string, err error) { 175 isString := false 176 177 switch { 178 case attribute.Id.Equal(oidFriendlyName): 179 key = "friendlyName" 180 isString = true 181 case attribute.Id.Equal(oidLocalKeyID): 182 key = "localKeyId" 183 case attribute.Id.Equal(oidMicrosoftCSPName): 184 // This key is chosen to match OpenSSL. 185 key = "Microsoft CSP Name" 186 isString = true 187 default: 188 return "", "", errors.New("pkcs12: unknown attribute with OID " + attribute.Id.String()) 189 } 190 191 if isString { 192 if err := unmarshal(attribute.Value.Bytes, &attribute.Value); err != nil { 193 return "", "", err 194 } 195 if value, err = decodeBMPString(attribute.Value.Bytes); err != nil { 196 return "", "", err 197 } 198 } else { 199 var id []byte 200 if err := unmarshal(attribute.Value.Bytes, &id); err != nil { 201 return "", "", err 202 } 203 value = hex.EncodeToString(id) 204 } 205 206 return key, value, nil 207 } 208 209 // Decode extracts a certificate and private key from pfxData. This function 210 // assumes that there is only one certificate and only one private key in the 211 // pfxData. 212 func Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error) { 213 encodedPassword, err := bmpString(password) 214 if err != nil { 215 return nil, nil, err 216 } 217 218 bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword) 219 if err != nil { 220 return nil, nil, err 221 } 222 223 if len(bags) != 2 { 224 err = errors.New("pkcs12: expected exactly two safe bags in the PFX PDU") 225 return 226 } 227 228 for _, bag := range bags { 229 switch { 230 case bag.Id.Equal(oidCertBag): 231 if certificate != nil { 232 err = errors.New("pkcs12: expected exactly one certificate bag") 233 } 234 235 certsData, err := decodeCertBag(bag.Value.Bytes) 236 if err != nil { 237 return nil, nil, err 238 } 239 certs, err := x509.ParseCertificates(certsData) 240 if err != nil { 241 return nil, nil, err 242 } 243 if len(certs) != 1 { 244 err = errors.New("pkcs12: expected exactly one certificate in the certBag") 245 return nil, nil, err 246 } 247 certificate = certs[0] 248 249 case bag.Id.Equal(oidPKCS8ShroudedKeyBag): 250 if privateKey != nil { 251 err = errors.New("pkcs12: expected exactly one key bag") 252 } 253 if privateKey, err = decodePkcs8ShroudedKeyBag(bag.Value.Bytes, encodedPassword); err != nil { 254 return nil, nil, err 255 } 256 } 257 } 258 259 if certificate == nil { 260 return nil, nil, errors.New("pkcs12: certificate missing") 261 } 262 if privateKey == nil { 263 return nil, nil, errors.New("pkcs12: private key missing") 264 } 265 266 return 267 } 268 269 func getLocalKeyId(id []byte) (attribute pkcs12Attribute, err error) { 270 octetString := asn1.RawValue{Tag: 4, Class: 0, IsCompound: false, Bytes: id} 271 bytes, err := asn1.Marshal(octetString) 272 if err != nil { 273 return 274 } 275 276 attribute = pkcs12Attribute{ 277 Id: oidLocalKeyID, 278 Value: asn1.RawValue{Tag: 17, Class: 0, IsCompound: true, Bytes: bytes}, 279 } 280 281 return attribute, nil 282 } 283 284 func convertToRawVal(val interface{}) (raw asn1.RawValue, err error) { 285 bytes, err := asn1.Marshal(val) 286 if err != nil { 287 return 288 } 289 290 _, err = asn1.Unmarshal(bytes, &raw) 291 return raw, nil 292 } 293 294 func makeSafeBags(oid asn1.ObjectIdentifier, value []byte) ([]safeBag, error) { 295 attribute, err := getLocalKeyId(localKeyId) 296 297 if err != nil { 298 return nil, EncodeError("local key id: " + err.Error()) 299 } 300 301 bag := make([]safeBag, 1) 302 bag[0] = safeBag{ 303 Id: oid, 304 Value: asn1.RawValue{Tag: 0, Class: 2, IsCompound: true, Bytes: value}, 305 Attributes: []pkcs12Attribute{attribute}, 306 } 307 308 return bag, nil 309 } 310 311 func makeCertBagContentInfo(derBytes []byte) (*contentInfo, error) { 312 certBag1 := certBag{ 313 Id: oidCertTypeX509Certificate, 314 Data: derBytes, 315 } 316 317 bytes, err := asn1.Marshal(certBag1) 318 if err != nil { 319 return nil, EncodeError("encoding cert bag: " + err.Error()) 320 } 321 322 certSafeBags, err := makeSafeBags(oidCertBag, bytes) 323 if err != nil { 324 return nil, EncodeError("safe bags: " + err.Error()) 325 } 326 327 return makeContentInfo(certSafeBags) 328 } 329 330 func makeShroudedKeyBagContentInfo(privateKey interface{}, password []byte) (*contentInfo, error) { 331 shroudedKeyBagBytes, err := encodePkcs8ShroudedKeyBag(privateKey, password) 332 if err != nil { 333 return nil, EncodeError("encode PKCS#8 shrouded key bag: " + err.Error()) 334 } 335 336 safeBags, err := makeSafeBags(oidPKCS8ShroudedKeyBag, shroudedKeyBagBytes) 337 if err != nil { 338 return nil, EncodeError("safe bags: " + err.Error()) 339 } 340 341 return makeContentInfo(safeBags) 342 } 343 344 func makeContentInfo(val interface{}) (*contentInfo, error) { 345 fullBytes, err := asn1.Marshal(val) 346 if err != nil { 347 return nil, EncodeError("contentInfo raw value marshal: " + err.Error()) 348 } 349 350 octetStringVal := asn1.RawValue{Tag: 4, Class: 0, IsCompound: false, Bytes: fullBytes} 351 octetStringFullBytes, err := asn1.Marshal(octetStringVal) 352 if err != nil { 353 return nil, EncodeError("raw contentInfo to octet string: " + err.Error()) 354 } 355 356 contentInfo := contentInfo{ContentType: oidDataContentType} 357 contentInfo.Content = asn1.RawValue{Tag: 0, Class: 2, IsCompound: true, Bytes: octetStringFullBytes} 358 359 return &contentInfo, nil 360 } 361 362 func makeContentInfos(derBytes []byte, privateKey interface{}, password []byte) ([]contentInfo, error) { 363 shroudedKeyContentInfo, err := makeShroudedKeyBagContentInfo(privateKey, password) 364 if err != nil { 365 return nil, EncodeError("shrouded key content info: " + err.Error()) 366 } 367 368 certBagContentInfo, err := makeCertBagContentInfo(derBytes) 369 if err != nil { 370 return nil, EncodeError("cert bag content info: " + err.Error()) 371 } 372 373 contentInfos := make([]contentInfo, 2) 374 contentInfos[0] = *shroudedKeyContentInfo 375 contentInfos[1] = *certBagContentInfo 376 377 return contentInfos, nil 378 } 379 380 func makeSalt(saltByteCount int) ([]byte, error) { 381 salt := make([]byte, saltByteCount) 382 _, err := io.ReadFull(rand.Reader, salt) 383 return salt, err 384 } 385 386 // Encode converts a certificate and a private key to the PKCS#12 byte stream format. 387 // 388 // derBytes is a DER encoded certificate. 389 // privateKey is an RSA 390 func Encode(derBytes []byte, privateKey interface{}, password string) (pfxBytes []byte, err error) { 391 secret, err := bmpString(password) 392 if err != nil { 393 return nil, ErrIncorrectPassword 394 } 395 396 contentInfos, err := makeContentInfos(derBytes, privateKey, secret) 397 if err != nil { 398 return nil, err 399 } 400 401 // Marshal []contentInfo so we can re-constitute the byte stream that will 402 // be suitable for computing the MAC 403 bytes, err := asn1.Marshal(contentInfos) 404 if err != nil { 405 return nil, err 406 } 407 408 // Unmarshal as an asn1.RawValue so, we can compute the MAC against the .Bytes 409 var contentInfosRaw asn1.RawValue 410 err = unmarshal(bytes, &contentInfosRaw) 411 if err != nil { 412 return nil, err 413 } 414 415 authSafeContentInfo, err := makeContentInfo(contentInfosRaw) 416 if err != nil { 417 return nil, EncodeError("authSafe content info: " + err.Error()) 418 } 419 420 salt, err := makeSalt(pbeSaltSizeBytes) 421 if err != nil { 422 return nil, EncodeError("salt value: " + err.Error()) 423 } 424 425 // Compute the MAC for marshaled bytes of contentInfos, which includes the 426 // cert bag, and the shrouded key bag. 427 digest := computeMac(contentInfosRaw.FullBytes, pbeIterationCount, salt, secret) 428 429 pfx := pfxPdu{ 430 Version: 3, 431 AuthSafe: *authSafeContentInfo, 432 MacData: macData{ 433 Iterations: pbeIterationCount, 434 MacSalt: salt, 435 Mac: digestInfo{ 436 Algorithm: pkix.AlgorithmIdentifier{ 437 Algorithm: oidSHA1, 438 }, 439 Digest: digest, 440 }, 441 }, 442 } 443 444 bytes, err = asn1.Marshal(pfx) 445 if err != nil { 446 return nil, EncodeError("marshal PFX PDU: " + err.Error()) 447 } 448 449 return bytes, err 450 } 451 452 func getSafeContents(p12Data, password []byte) (bags []safeBag, updatedPassword []byte, err error) { 453 pfx := new(pfxPdu) 454 455 if err := unmarshal(p12Data, pfx); err != nil { 456 return nil, nil, errors.New("pkcs12: error reading P12 data: " + err.Error()) 457 } 458 459 if pfx.Version != 3 { 460 return nil, nil, NotImplementedError("can only decode v3 PFX PDU's") 461 } 462 463 if !pfx.AuthSafe.ContentType.Equal(oidDataContentType) { 464 return nil, nil, NotImplementedError("only password-protected PFX is implemented") 465 } 466 467 // unmarshal the explicit bytes in the content for type 'data' 468 if err := unmarshal(pfx.AuthSafe.Content.Bytes, &pfx.AuthSafe.Content); err != nil { 469 return nil, nil, err 470 } 471 472 if len(pfx.MacData.Mac.Algorithm.Algorithm) == 0 { 473 return nil, nil, errors.New("pkcs12: no MAC in data") 474 } 475 476 if err := verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password); err != nil { 477 if err == ErrIncorrectPassword && len(password) == 2 && password[0] == 0 && password[1] == 0 { 478 // some implementations use an empty byte array 479 // for the empty string password try one more 480 // time with empty-empty password 481 password = nil 482 err = verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password) 483 } 484 if err != nil { 485 return nil, nil, err 486 } 487 } 488 489 var authenticatedSafe []contentInfo 490 if err := unmarshal(pfx.AuthSafe.Content.Bytes, &authenticatedSafe); err != nil { 491 return nil, nil, err 492 } 493 494 if len(authenticatedSafe) != 2 { 495 return nil, nil, NotImplementedError("expected exactly two items in the authenticated safe") 496 } 497 498 for _, ci := range authenticatedSafe { 499 var data []byte 500 501 switch { 502 case ci.ContentType.Equal(oidDataContentType): 503 if err := unmarshal(ci.Content.Bytes, &data); err != nil { 504 return nil, nil, err 505 } 506 case ci.ContentType.Equal(oidEncryptedDataContentType): 507 var encryptedData encryptedData 508 if err := unmarshal(ci.Content.Bytes, &encryptedData); err != nil { 509 return nil, nil, err 510 } 511 if encryptedData.Version != 0 { 512 return nil, nil, NotImplementedError("only version 0 of EncryptedData is supported") 513 } 514 if data, err = pbDecrypt(encryptedData.EncryptedContentInfo, password); err != nil { 515 return nil, nil, err 516 } 517 default: 518 return nil, nil, NotImplementedError("only data and encryptedData content types are supported in authenticated safe") 519 } 520 521 var safeContents []safeBag 522 if err := unmarshal(data, &safeContents); err != nil { 523 return nil, nil, err 524 } 525 526 bags = append(bags, safeContents...) 527 } 528 529 return bags, password, nil 530 }