~juju-qa/ubuntu/xenial/juju/2.0-rc2

« back to all changes in this revision

Viewing changes to src/golang.org/x/crypto/pkcs12/crypto.go

  • Committer: Nicholas Skaggs
  • Date: 2016-09-30 14:39:30 UTC
  • mfrom: (1.8.1)
  • Revision ID: nicholas.skaggs@canonical.com-20160930143930-vwwhrefh6ftckccy
import upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
6
 
 
7
import (
 
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
 
 
18
var (
 
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.
 
24
type 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
 
 
33
type shaWithTripleDESCBC struct{}
 
34
 
 
35
func (shaWithTripleDESCBC) create(key []byte) (cipher.Block, error) {
 
36
        return des.NewTripleDESCipher(key)
 
37
}
 
38
 
 
39
func (shaWithTripleDESCBC) deriveKey(salt, password []byte, iterations int) []byte {
 
40
        return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 24)
 
41
}
 
42
 
 
43
func (shaWithTripleDESCBC) deriveIV(salt, password []byte, iterations int) []byte {
 
44
        return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
 
45
}
 
46
 
 
47
type shaWith40BitRC2CBC struct{}
 
48
 
 
49
func (shaWith40BitRC2CBC) create(key []byte) (cipher.Block, error) {
 
50
        return rc2.New(key, len(key)*8)
 
51
}
 
52
 
 
53
func (shaWith40BitRC2CBC) deriveKey(salt, password []byte, iterations int) []byte {
 
54
        return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 5)
 
55
}
 
56
 
 
57
func (shaWith40BitRC2CBC) deriveIV(salt, password []byte, iterations int) []byte {
 
58
        return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
 
59
}
 
60
 
 
61
type pbeParams struct {
 
62
        Salt       []byte
 
63
        Iterations int
 
64
}
 
65
 
 
66
func 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, &params); 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
 
 
94
func 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 a object that contains ciphertext.
 
128
type decryptable interface {
 
129
        Algorithm() pkix.AlgorithmIdentifier
 
130
        Data() []byte
 
131
}