/src/boringssl/crypto/evp/p_dsa.cc
Line | Count | Source |
1 | | // Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include <openssl/evp.h> |
16 | | |
17 | | #include <openssl/bn.h> |
18 | | #include <openssl/bytestring.h> |
19 | | #include <openssl/digest.h> |
20 | | #include <openssl/dsa.h> |
21 | | #include <openssl/err.h> |
22 | | |
23 | | #include "../dsa/internal.h" |
24 | | #include "internal.h" |
25 | | |
26 | | |
27 | | namespace { |
28 | | |
29 | | extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meth; |
30 | | |
31 | | static evp_decode_result_t dsa_pub_decode(const EVP_PKEY_ALG *alg, |
32 | | EVP_PKEY *out, CBS *params, |
33 | 4.22k | CBS *key) { |
34 | | // See RFC 3279, section 2.3.2. |
35 | | |
36 | | // Decode parameters. RFC 3279 permits DSA parameters to be omitted, in which |
37 | | // case they are implicitly determined from the issuing certificate, or |
38 | | // somewhere unspecified and out-of-band. We do not support this mode. |
39 | 4.22k | bssl::UniquePtr<DSA> dsa(DSA_parse_parameters(params)); |
40 | 4.22k | if (dsa == nullptr || CBS_len(params) != 0) { |
41 | 4.16k | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); |
42 | 4.16k | return evp_decode_error; |
43 | 4.16k | } |
44 | | |
45 | 58 | dsa->pub_key = BN_new(); |
46 | 58 | if (dsa->pub_key == nullptr) { |
47 | 0 | return evp_decode_error; |
48 | 0 | } |
49 | | |
50 | 58 | if (!BN_parse_asn1_unsigned(key, dsa->pub_key) || CBS_len(key) != 0) { |
51 | 41 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); |
52 | 41 | return evp_decode_error; |
53 | 41 | } |
54 | | |
55 | 17 | EVP_PKEY_assign_DSA(out, dsa.release()); |
56 | 17 | return evp_decode_ok; |
57 | 58 | } |
58 | | |
59 | 237 | static int dsa_pub_encode(CBB *out, const EVP_PKEY *key) { |
60 | 237 | const DSA *dsa = reinterpret_cast<const DSA *>(key->pkey); |
61 | 237 | const int has_params = |
62 | 237 | dsa->p != nullptr && dsa->q != nullptr && dsa->g != nullptr; |
63 | | |
64 | | // See RFC 5480, section 2. |
65 | 237 | CBB spki, algorithm, key_bitstring; |
66 | 237 | if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || |
67 | 237 | !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || |
68 | 237 | !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, dsa_asn1_meth.oid, |
69 | 237 | dsa_asn1_meth.oid_len) || |
70 | 237 | (has_params && !DSA_marshal_parameters(&algorithm, dsa)) || |
71 | 237 | !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || |
72 | 237 | !CBB_add_u8(&key_bitstring, 0 /* padding */) || |
73 | 237 | !BN_marshal_asn1(&key_bitstring, dsa->pub_key) || !CBB_flush(out)) { |
74 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); |
75 | 0 | return 0; |
76 | 0 | } |
77 | | |
78 | 237 | return 1; |
79 | 237 | } |
80 | | |
81 | | static evp_decode_result_t dsa_priv_decode(const EVP_PKEY_ALG *alg, |
82 | | EVP_PKEY *out, CBS *params, |
83 | 2.10k | CBS *key) { |
84 | | // See PKCS#11, v2.40, section 2.5. |
85 | | |
86 | | // Decode parameters. |
87 | 2.10k | bssl::UniquePtr<DSA> dsa(DSA_parse_parameters(params)); |
88 | 2.10k | if (dsa == nullptr || CBS_len(params) != 0) { |
89 | 1.19k | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); |
90 | 1.19k | return evp_decode_error; |
91 | 1.19k | } |
92 | | |
93 | 907 | dsa->priv_key = BN_new(); |
94 | 907 | if (dsa->priv_key == nullptr) { |
95 | 0 | return evp_decode_error; |
96 | 0 | } |
97 | 907 | if (!BN_parse_asn1_unsigned(key, dsa->priv_key) || CBS_len(key) != 0) { |
98 | 13 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); |
99 | 13 | return evp_decode_error; |
100 | 13 | } |
101 | | |
102 | | // To avoid DoS attacks when importing private keys, check bounds on |dsa|. |
103 | | // This bounds |dsa->priv_key| against |dsa->q| and bounds |dsa->q|'s bit |
104 | | // width. |
105 | 894 | if (!dsa_check_key(dsa.get())) { |
106 | 14 | OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); |
107 | 14 | return evp_decode_error; |
108 | 14 | } |
109 | | |
110 | | // Calculate the public key. |
111 | 880 | bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new()); |
112 | 880 | dsa->pub_key = BN_new(); |
113 | 880 | if (ctx == nullptr || dsa->pub_key == nullptr || |
114 | 880 | !BN_mod_exp_mont_consttime(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, |
115 | 880 | ctx.get(), nullptr)) { |
116 | 0 | return evp_decode_error; |
117 | 0 | } |
118 | | |
119 | 880 | EVP_PKEY_assign_DSA(out, dsa.release()); |
120 | 880 | return evp_decode_ok; |
121 | 880 | } |
122 | | |
123 | 671 | static int dsa_priv_encode(CBB *out, const EVP_PKEY *key) { |
124 | 671 | const DSA *dsa = reinterpret_cast<const DSA *>(key->pkey); |
125 | 671 | if (dsa == nullptr || dsa->priv_key == nullptr) { |
126 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS); |
127 | 0 | return 0; |
128 | 0 | } |
129 | | |
130 | | // See PKCS#11, v2.40, section 2.5. |
131 | 671 | CBB pkcs8, algorithm, private_key; |
132 | 671 | if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || |
133 | 671 | !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || |
134 | 671 | !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || |
135 | 671 | !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, dsa_asn1_meth.oid, |
136 | 671 | dsa_asn1_meth.oid_len) || |
137 | 671 | !DSA_marshal_parameters(&algorithm, dsa) || |
138 | 671 | !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || |
139 | 671 | !BN_marshal_asn1(&private_key, dsa->priv_key) || !CBB_flush(out)) { |
140 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); |
141 | 0 | return 0; |
142 | 0 | } |
143 | | |
144 | 671 | return 1; |
145 | 671 | } |
146 | | |
147 | 0 | static int int_dsa_size(const EVP_PKEY *pkey) { |
148 | 0 | const DSA *dsa = reinterpret_cast<const DSA *>(pkey->pkey); |
149 | 0 | return DSA_size(dsa); |
150 | 0 | } |
151 | | |
152 | 0 | static int dsa_bits(const EVP_PKEY *pkey) { |
153 | 0 | const DSA *dsa = reinterpret_cast<const DSA *>(pkey->pkey); |
154 | 0 | return BN_num_bits(DSA_get0_p(dsa)); |
155 | 0 | } |
156 | | |
157 | 0 | static int dsa_missing_parameters(const EVP_PKEY *pkey) { |
158 | 0 | const DSA *dsa = reinterpret_cast<const DSA *>(pkey->pkey); |
159 | 0 | if (DSA_get0_p(dsa) == nullptr || DSA_get0_q(dsa) == nullptr || |
160 | 0 | DSA_get0_g(dsa) == nullptr) { |
161 | 0 | return 1; |
162 | 0 | } |
163 | 0 | return 0; |
164 | 0 | } |
165 | | |
166 | 0 | static int dup_bn_into(BIGNUM **out, BIGNUM *src) { |
167 | 0 | bssl::UniquePtr<BIGNUM> a(BN_dup(src)); |
168 | 0 | if (a == nullptr) { |
169 | 0 | return 0; |
170 | 0 | } |
171 | 0 | BN_free(*out); |
172 | 0 | *out = a.release(); |
173 | 0 | return 1; |
174 | 0 | } |
175 | | |
176 | 0 | static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { |
177 | 0 | DSA *to_dsa = reinterpret_cast<DSA *>(to->pkey); |
178 | 0 | const DSA *from_dsa = reinterpret_cast<const DSA *>(from->pkey); |
179 | 0 | if (!dup_bn_into(&to_dsa->p, from_dsa->p) || |
180 | 0 | !dup_bn_into(&to_dsa->q, from_dsa->q) || |
181 | 0 | !dup_bn_into(&to_dsa->g, from_dsa->g)) { |
182 | 0 | return 0; |
183 | 0 | } |
184 | | |
185 | 0 | return 1; |
186 | 0 | } |
187 | | |
188 | 0 | static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) { |
189 | 0 | const DSA *a_dsa = reinterpret_cast<const DSA *>(a->pkey); |
190 | 0 | const DSA *b_dsa = reinterpret_cast<const DSA *>(b->pkey); |
191 | 0 | return BN_cmp(DSA_get0_p(a_dsa), DSA_get0_p(b_dsa)) == 0 && |
192 | 0 | BN_cmp(DSA_get0_q(a_dsa), DSA_get0_q(b_dsa)) == 0 && |
193 | 0 | BN_cmp(DSA_get0_g(a_dsa), DSA_get0_g(b_dsa)) == 0; |
194 | 0 | } |
195 | | |
196 | 0 | static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { |
197 | 0 | const DSA *a_dsa = reinterpret_cast<const DSA *>(a->pkey); |
198 | 0 | const DSA *b_dsa = reinterpret_cast<const DSA *>(b->pkey); |
199 | 0 | return BN_cmp(DSA_get0_pub_key(b_dsa), DSA_get0_pub_key(a_dsa)) == 0; |
200 | 0 | } |
201 | | |
202 | 902 | static void int_dsa_free(EVP_PKEY *pkey) { |
203 | 902 | DSA_free(reinterpret_cast<DSA *>(pkey->pkey)); |
204 | 902 | pkey->pkey = nullptr; |
205 | 902 | } |
206 | | |
207 | | const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = { |
208 | | EVP_PKEY_DSA, |
209 | | // 1.2.840.10040.4.1 |
210 | | {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01}, |
211 | | 7, |
212 | | |
213 | | /*pkey_method=*/nullptr, |
214 | | |
215 | | dsa_pub_decode, |
216 | | dsa_pub_encode, |
217 | | dsa_pub_cmp, |
218 | | |
219 | | dsa_priv_decode, |
220 | | dsa_priv_encode, |
221 | | |
222 | | /*set_priv_raw=*/nullptr, |
223 | | /*set_priv_seed=*/nullptr, |
224 | | /*set_pub_raw=*/nullptr, |
225 | | /*get_priv_raw=*/nullptr, |
226 | | /*get_priv_seed=*/nullptr, |
227 | | /*get_pub_raw=*/nullptr, |
228 | | /*set1_tls_encodedpoint=*/nullptr, |
229 | | /*get1_tls_encodedpoint=*/nullptr, |
230 | | |
231 | | /*pkey_opaque=*/nullptr, |
232 | | |
233 | | int_dsa_size, |
234 | | dsa_bits, |
235 | | |
236 | | dsa_missing_parameters, |
237 | | dsa_copy_parameters, |
238 | | dsa_cmp_parameters, |
239 | | |
240 | | int_dsa_free, |
241 | | }; |
242 | | |
243 | | } // namespace |
244 | | |
245 | 218k | const EVP_PKEY_ALG *EVP_pkey_dsa(void) { |
246 | 218k | static const EVP_PKEY_ALG kAlg = {&dsa_asn1_meth}; |
247 | 218k | return &kAlg; |
248 | 218k | } |
249 | | |
250 | 0 | int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX *ctx, int nbits) { |
251 | | // BoringSSL does not support DSA in |EVP_PKEY_CTX|. |
252 | 0 | OPENSSL_PUT_ERROR(EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
253 | 0 | return 0; |
254 | 0 | } |
255 | | |
256 | 0 | int EVP_PKEY_CTX_set_dsa_paramgen_q_bits(EVP_PKEY_CTX *ctx, int qbits) { |
257 | | // BoringSSL does not support DSA in |EVP_PKEY_CTX|. |
258 | 0 | OPENSSL_PUT_ERROR(EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
259 | 0 | return 0; |
260 | 0 | } |
261 | | |
262 | 0 | int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) { |
263 | 0 | if (EVP_PKEY_assign_DSA(pkey, key)) { |
264 | 0 | DSA_up_ref(key); |
265 | 0 | return 1; |
266 | 0 | } |
267 | 0 | return 0; |
268 | 0 | } |
269 | | |
270 | 902 | int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key) { |
271 | 902 | if (key == nullptr) { |
272 | 0 | return 0; |
273 | 0 | } |
274 | 902 | evp_pkey_set0(pkey, &dsa_asn1_meth, key); |
275 | 902 | return 1; |
276 | 902 | } |
277 | | |
278 | 0 | DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey) { |
279 | 0 | if (EVP_PKEY_id(pkey) != EVP_PKEY_DSA) { |
280 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_A_DSA_KEY); |
281 | 0 | return nullptr; |
282 | 0 | } |
283 | 0 | return reinterpret_cast<DSA *>(pkey->pkey); |
284 | 0 | } |
285 | | |
286 | 0 | DSA *EVP_PKEY_get1_DSA(const EVP_PKEY *pkey) { |
287 | 0 | DSA *dsa = EVP_PKEY_get0_DSA(pkey); |
288 | 0 | if (dsa != nullptr) { |
289 | 0 | DSA_up_ref(dsa); |
290 | 0 | } |
291 | 0 | return dsa; |
292 | 0 | } |