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 5package pkcs12 6 7import ( 8 "bytes" 9 "crypto/cipher" 10 "crypto/des" 11 "crypto/x509/pkix" 12 "encoding/asn1" 13 "errors" 14 15 "golang.org/x/crypto/pkcs12/internal/rc2" 16) 17 18var ( 19 oidPBEWithSHAAnd3KeyTripleDESCBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}) 20 oidPBEWithSHAAnd40BitRC2CBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 6}) 21) 22 23// pbeCipher is an abstraction of a PKCS#12 cipher. 24type pbeCipher interface { 25 // create returns a cipher.Block given a key. 26 create(key []byte) (cipher.Block, error) 27 // deriveKey returns a key derived from the given password and salt. 28 deriveKey(salt, password []byte, iterations int) []byte 29 // deriveKey returns an IV derived from the given password and salt. 30 deriveIV(salt, password []byte, iterations int) []byte 31} 32 33type shaWithTripleDESCBC struct{} 34 35func (shaWithTripleDESCBC) create(key []byte) (cipher.Block, error) { 36 return des.NewTripleDESCipher(key) 37} 38 39func (shaWithTripleDESCBC) deriveKey(salt, password []byte, iterations int) []byte { 40 return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 24) 41} 42 43func (shaWithTripleDESCBC) deriveIV(salt, password []byte, iterations int) []byte { 44 return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8) 45} 46 47type shaWith40BitRC2CBC struct{} 48 49func (shaWith40BitRC2CBC) create(key []byte) (cipher.Block, error) { 50 return rc2.New(key, len(key)*8) 51} 52 53func (shaWith40BitRC2CBC) deriveKey(salt, password []byte, iterations int) []byte { 54 return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 5) 55} 56 57func (shaWith40BitRC2CBC) deriveIV(salt, password []byte, iterations int) []byte { 58 return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8) 59} 60 61type pbeParams struct { 62 Salt []byte 63 Iterations int 64} 65 66func pbDecrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) { 67 var cipherType pbeCipher 68 69 switch { 70 case algorithm.Algorithm.Equal(oidPBEWithSHAAnd3KeyTripleDESCBC): 71 cipherType = shaWithTripleDESCBC{} 72 case algorithm.Algorithm.Equal(oidPBEWithSHAAnd40BitRC2CBC): 73 cipherType = shaWith40BitRC2CBC{} 74 default: 75 return nil, 0, NotImplementedError("algorithm " + algorithm.Algorithm.String() + " is not supported") 76 } 77 78 var params pbeParams 79 if err := unmarshal(algorithm.Parameters.FullBytes, ¶ms); err != nil { 80 return nil, 0, err 81 } 82 83 key := cipherType.deriveKey(params.Salt, password, params.Iterations) 84 iv := cipherType.deriveIV(params.Salt, password, params.Iterations) 85 86 block, err := cipherType.create(key) 87 if err != nil { 88 return nil, 0, err 89 } 90 91 return cipher.NewCBCDecrypter(block, iv), block.BlockSize(), nil 92} 93 94func pbDecrypt(info decryptable, password []byte) (decrypted []byte, err error) { 95 cbc, blockSize, err := pbDecrypterFor(info.Algorithm(), password) 96 if err != nil { 97 return nil, err 98 } 99 100 encrypted := info.Data() 101 if len(encrypted) == 0 { 102 return nil, errors.New("pkcs12: empty encrypted data") 103 } 104 if len(encrypted)%blockSize != 0 { 105 return nil, errors.New("pkcs12: input is not a multiple of the block size") 106 } 107 decrypted = make([]byte, len(encrypted)) 108 cbc.CryptBlocks(decrypted, encrypted) 109 110 psLen := int(decrypted[len(decrypted)-1]) 111 if psLen == 0 || psLen > blockSize { 112 return nil, ErrDecryption 113 } 114 115 if len(decrypted) < psLen { 116 return nil, ErrDecryption 117 } 118 ps := decrypted[len(decrypted)-psLen:] 119 decrypted = decrypted[:len(decrypted)-psLen] 120 if bytes.Compare(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) != 0 { 121 return nil, ErrDecryption 122 } 123 124 return 125} 126 127// decryptable abstracts an object that contains ciphertext. 128type decryptable interface { 129 Algorithm() pkix.AlgorithmIdentifier 130 Data() []byte 131} 132