Fix bootstrap/PR63632
[official-gcc.git] / libgo / go / crypto / rsa / pkcs1v15.go
blobd9957aec1d64f0f8b3ed72aeb1ae4f012124f325
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.
5 package rsa
7 import (
8 "crypto"
9 "crypto/subtle"
10 "errors"
11 "io"
12 "math/big"
15 // This file implements encryption and decryption using PKCS#1 v1.5 padding.
17 // EncryptPKCS1v15 encrypts the given message with RSA and the padding scheme from PKCS#1 v1.5.
18 // The message must be no longer than the length of the public modulus minus 11 bytes.
19 // WARNING: use of this function to encrypt plaintexts other than session keys
20 // is dangerous. Use RSA OAEP in new protocols.
21 func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err error) {
22 if err := checkPub(pub); err != nil {
23 return nil, err
25 k := (pub.N.BitLen() + 7) / 8
26 if len(msg) > k-11 {
27 err = ErrMessageTooLong
28 return
31 // EM = 0x00 || 0x02 || PS || 0x00 || M
32 em := make([]byte, k)
33 em[1] = 2
34 ps, mm := em[2:len(em)-len(msg)-1], em[len(em)-len(msg):]
35 err = nonZeroRandomBytes(ps, rand)
36 if err != nil {
37 return
39 em[len(em)-len(msg)-1] = 0
40 copy(mm, msg)
42 m := new(big.Int).SetBytes(em)
43 c := encrypt(new(big.Int), pub, m)
45 copyWithLeftPad(em, c.Bytes())
46 out = em
47 return
50 // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
51 // If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
52 func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error) {
53 if err := checkPub(&priv.PublicKey); err != nil {
54 return nil, err
56 valid, out, err := decryptPKCS1v15(rand, priv, ciphertext)
57 if err == nil && valid == 0 {
58 err = ErrDecryption
61 return
64 // DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding scheme from PKCS#1 v1.5.
65 // If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
66 // It returns an error if the ciphertext is the wrong length or if the
67 // ciphertext is greater than the public modulus. Otherwise, no error is
68 // returned. If the padding is valid, the resulting plaintext message is copied
69 // into key. Otherwise, key is unchanged. These alternatives occur in constant
70 // time. It is intended that the user of this function generate a random
71 // session key beforehand and continue the protocol with the resulting value.
72 // This will remove any possibility that an attacker can learn any information
73 // about the plaintext.
74 // See ``Chosen Ciphertext Attacks Against Protocols Based on the RSA
75 // Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology
76 // (Crypto '98).
77 func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) {
78 if err := checkPub(&priv.PublicKey); err != nil {
79 return err
81 k := (priv.N.BitLen() + 7) / 8
82 if k-(len(key)+3+8) < 0 {
83 err = ErrDecryption
84 return
87 valid, msg, err := decryptPKCS1v15(rand, priv, ciphertext)
88 if err != nil {
89 return
92 valid &= subtle.ConstantTimeEq(int32(len(msg)), int32(len(key)))
93 subtle.ConstantTimeCopy(valid, key, msg)
94 return
97 func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, msg []byte, err error) {
98 k := (priv.N.BitLen() + 7) / 8
99 if k < 11 {
100 err = ErrDecryption
101 return
104 c := new(big.Int).SetBytes(ciphertext)
105 m, err := decrypt(rand, priv, c)
106 if err != nil {
107 return
110 em := leftPad(m.Bytes(), k)
111 firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
112 secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2)
114 // The remainder of the plaintext must be a string of non-zero random
115 // octets, followed by a 0, followed by the message.
116 // lookingForIndex: 1 iff we are still looking for the zero.
117 // index: the offset of the first zero byte.
118 var lookingForIndex, index int
119 lookingForIndex = 1
121 for i := 2; i < len(em); i++ {
122 equals0 := subtle.ConstantTimeByteEq(em[i], 0)
123 index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
124 lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
127 // The PS padding must be at least 8 bytes long, and it starts two
128 // bytes into em.
129 validPS := subtle.ConstantTimeLessOrEq(2+8, index)
131 valid = firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1) & validPS
132 msg = em[index+1:]
133 return
136 // nonZeroRandomBytes fills the given slice with non-zero random octets.
137 func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
138 _, err = io.ReadFull(rand, s)
139 if err != nil {
140 return
143 for i := 0; i < len(s); i++ {
144 for s[i] == 0 {
145 _, err = io.ReadFull(rand, s[i:i+1])
146 if err != nil {
147 return
149 // In tests, the PRNG may return all zeros so we do
150 // this to break the loop.
151 s[i] ^= 0x42
155 return
158 // These are ASN1 DER structures:
159 // DigestInfo ::= SEQUENCE {
160 // digestAlgorithm AlgorithmIdentifier,
161 // digest OCTET STRING
162 // }
163 // For performance, we don't use the generic ASN1 encoder. Rather, we
164 // precompute a prefix of the digest value that makes a valid ASN1 DER string
165 // with the correct contents.
166 var hashPrefixes = map[crypto.Hash][]byte{
167 crypto.MD5: {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
168 crypto.SHA1: {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
169 crypto.SHA224: {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
170 crypto.SHA256: {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
171 crypto.SHA384: {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
172 crypto.SHA512: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
173 crypto.MD5SHA1: {}, // A special TLS case which doesn't use an ASN1 prefix.
174 crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
177 // SignPKCS1v15 calculates the signature of hashed using RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5.
178 // Note that hashed must be the result of hashing the input message using the
179 // given hash function. If hash is zero, hashed is signed directly. This isn't
180 // advisable except for interoperability.
181 func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err error) {
182 hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
183 if err != nil {
184 return
187 tLen := len(prefix) + hashLen
188 k := (priv.N.BitLen() + 7) / 8
189 if k < tLen+11 {
190 return nil, ErrMessageTooLong
193 // EM = 0x00 || 0x01 || PS || 0x00 || T
194 em := make([]byte, k)
195 em[1] = 1
196 for i := 2; i < k-tLen-1; i++ {
197 em[i] = 0xff
199 copy(em[k-tLen:k-hashLen], prefix)
200 copy(em[k-hashLen:k], hashed)
202 m := new(big.Int).SetBytes(em)
203 c, err := decrypt(rand, priv, m)
204 if err != nil {
205 return
208 copyWithLeftPad(em, c.Bytes())
209 s = em
210 return
213 // VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature.
214 // hashed is the result of hashing the input message using the given hash
215 // function and sig is the signature. A valid signature is indicated by
216 // returning a nil error. If hash is zero then hashed is used directly. This
217 // isn't advisable except for interoperability.
218 func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (err error) {
219 hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
220 if err != nil {
221 return
224 tLen := len(prefix) + hashLen
225 k := (pub.N.BitLen() + 7) / 8
226 if k < tLen+11 {
227 err = ErrVerification
228 return
231 c := new(big.Int).SetBytes(sig)
232 m := encrypt(new(big.Int), pub, c)
233 em := leftPad(m.Bytes(), k)
234 // EM = 0x00 || 0x01 || PS || 0x00 || T
236 ok := subtle.ConstantTimeByteEq(em[0], 0)
237 ok &= subtle.ConstantTimeByteEq(em[1], 1)
238 ok &= subtle.ConstantTimeCompare(em[k-hashLen:k], hashed)
239 ok &= subtle.ConstantTimeCompare(em[k-tLen:k-hashLen], prefix)
240 ok &= subtle.ConstantTimeByteEq(em[k-tLen-1], 0)
242 for i := 2; i < k-tLen-1; i++ {
243 ok &= subtle.ConstantTimeByteEq(em[i], 0xff)
246 if ok != 1 {
247 return ErrVerification
250 return nil
253 func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) {
254 // Special case: crypto.Hash(0) is used to indicate that the data is
255 // signed directly.
256 if hash == 0 {
257 return inLen, nil, nil
260 hashLen = hash.Size()
261 if inLen != hashLen {
262 return 0, nil, errors.New("crypto/rsa: input must be hashed message")
264 prefix, ok := hashPrefixes[hash]
265 if !ok {
266 return 0, nil, errors.New("crypto/rsa: unsupported hash function")
268 return
271 // copyWithLeftPad copies src to the end of dest, padding with zero bytes as
272 // needed.
273 func copyWithLeftPad(dest, src []byte) {
274 numPaddingBytes := len(dest) - len(src)
275 for i := 0; i < numPaddingBytes; i++ {
276 dest[i] = 0
278 copy(dest[numPaddingBytes:], src)