1 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
2 * 2006.
3 */
4 /* ====================================================================
5 * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. All advertising materials mentioning features or use of this
20 * software must display the following acknowledgment:
21 * "This product includes software developed by the OpenSSL Project
22 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23 *
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25 * endorse or promote products derived from this software without
26 * prior written permission. For written permission, please contact
27 * licensing@OpenSSL.org.
28 *
29 * 5. Products derived from this software may not be called "OpenSSL"
30 * nor may "OpenSSL" appear in their names without prior written
31 * permission of the OpenSSL Project.
32 *
33 * 6. Redistributions of any form whatsoever must retain the following
34 * acknowledgment:
35 * "This product includes software developed by the OpenSSL Project
36 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 * ====================================================================
51 *
52 * This product includes cryptographic software written by Eric Young
53 * (eay@cryptsoft.com). This product includes software written by Tim
54 * Hudson (tjh@cryptsoft.com). */
55
56 #include <openssl/evp.h>
57
58 #include <openssl/digest.h>
59 #include <openssl/bn.h>
60 #include <openssl/bytestring.h>
61 #include <openssl/dsa.h>
62 #include <openssl/err.h>
63
64 #include "internal.h"
65
66
dsa_pub_decode(EVP_PKEY * out,CBS * params,CBS * key)67 static int dsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
68 // See RFC 3279, section 2.3.2.
69
70 // Parameters may or may not be present.
71 DSA *dsa;
72 if (CBS_len(params) == 0) {
73 dsa = DSA_new();
74 if (dsa == NULL) {
75 return 0;
76 }
77 } else {
78 dsa = DSA_parse_parameters(params);
79 if (dsa == NULL || CBS_len(params) != 0) {
80 OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
81 goto err;
82 }
83 }
84
85 dsa->pub_key = BN_new();
86 if (dsa->pub_key == NULL) {
87 goto err;
88 }
89
90 if (!BN_parse_asn1_unsigned(key, dsa->pub_key) ||
91 CBS_len(key) != 0) {
92 OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
93 goto err;
94 }
95
96 EVP_PKEY_assign_DSA(out, dsa);
97 return 1;
98
99 err:
100 DSA_free(dsa);
101 return 0;
102 }
103
dsa_pub_encode(CBB * out,const EVP_PKEY * key)104 static int dsa_pub_encode(CBB *out, const EVP_PKEY *key) {
105 const DSA *dsa = key->pkey.dsa;
106 const int has_params = dsa->p != NULL && dsa->q != NULL && dsa->g != NULL;
107
108 // See RFC 5480, section 2.
109 CBB spki, algorithm, oid, key_bitstring;
110 if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
111 !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
112 !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
113 !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
114 (has_params &&
115 !DSA_marshal_parameters(&algorithm, dsa)) ||
116 !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
117 !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
118 !BN_marshal_asn1(&key_bitstring, dsa->pub_key) ||
119 !CBB_flush(out)) {
120 OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
121 return 0;
122 }
123
124 return 1;
125 }
126
dsa_priv_decode(EVP_PKEY * out,CBS * params,CBS * key)127 static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
128 // See PKCS#11, v2.40, section 2.5.
129
130 // Decode parameters.
131 BN_CTX *ctx = NULL;
132 DSA *dsa = DSA_parse_parameters(params);
133 if (dsa == NULL || CBS_len(params) != 0) {
134 OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
135 goto err;
136 }
137
138 dsa->priv_key = BN_new();
139 dsa->pub_key = BN_new();
140 if (dsa->priv_key == NULL || dsa->pub_key == NULL) {
141 goto err;
142 }
143
144 // Decode the key. To avoid DoS attacks when importing private keys, we bound
145 // |dsa->priv_key| against |dsa->q|, which itself bound by
146 // |DSA_parse_parameters|. (We cannot call |BN_num_bits| on |dsa->priv_key|.
147 // That would leak a secret bit width.)
148 if (!BN_parse_asn1_unsigned(key, dsa->priv_key) ||
149 CBS_len(key) != 0 ||
150 BN_cmp(dsa->priv_key, dsa->q) >= 0) {
151 OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
152 goto err;
153 }
154
155 // Calculate the public key.
156 ctx = BN_CTX_new();
157 if (ctx == NULL ||
158 !BN_mod_exp_mont_consttime(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p,
159 ctx, NULL)) {
160 goto err;
161 }
162
163 BN_CTX_free(ctx);
164 EVP_PKEY_assign_DSA(out, dsa);
165 return 1;
166
167 err:
168 BN_CTX_free(ctx);
169 DSA_free(dsa);
170 return 0;
171 }
172
dsa_priv_encode(CBB * out,const EVP_PKEY * key)173 static int dsa_priv_encode(CBB *out, const EVP_PKEY *key) {
174 const DSA *dsa = key->pkey.dsa;
175 if (dsa == NULL || dsa->priv_key == NULL) {
176 OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
177 return 0;
178 }
179
180 // See PKCS#11, v2.40, section 2.5.
181 CBB pkcs8, algorithm, oid, private_key;
182 if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
183 !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
184 !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
185 !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
186 !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
187 !DSA_marshal_parameters(&algorithm, dsa) ||
188 !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
189 !BN_marshal_asn1(&private_key, dsa->priv_key) ||
190 !CBB_flush(out)) {
191 OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
192 return 0;
193 }
194
195 return 1;
196 }
197
int_dsa_size(const EVP_PKEY * pkey)198 static int int_dsa_size(const EVP_PKEY *pkey) {
199 return DSA_size(pkey->pkey.dsa);
200 }
201
dsa_bits(const EVP_PKEY * pkey)202 static int dsa_bits(const EVP_PKEY *pkey) {
203 return BN_num_bits(pkey->pkey.dsa->p);
204 }
205
dsa_missing_parameters(const EVP_PKEY * pkey)206 static int dsa_missing_parameters(const EVP_PKEY *pkey) {
207 DSA *dsa;
208 dsa = pkey->pkey.dsa;
209 if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
210 return 1;
211 }
212 return 0;
213 }
214
dup_bn_into(BIGNUM ** out,BIGNUM * src)215 static int dup_bn_into(BIGNUM **out, BIGNUM *src) {
216 BIGNUM *a;
217
218 a = BN_dup(src);
219 if (a == NULL) {
220 return 0;
221 }
222 BN_free(*out);
223 *out = a;
224
225 return 1;
226 }
227
dsa_copy_parameters(EVP_PKEY * to,const EVP_PKEY * from)228 static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
229 if (!dup_bn_into(&to->pkey.dsa->p, from->pkey.dsa->p) ||
230 !dup_bn_into(&to->pkey.dsa->q, from->pkey.dsa->q) ||
231 !dup_bn_into(&to->pkey.dsa->g, from->pkey.dsa->g)) {
232 return 0;
233 }
234
235 return 1;
236 }
237
dsa_cmp_parameters(const EVP_PKEY * a,const EVP_PKEY * b)238 static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
239 return BN_cmp(a->pkey.dsa->p, b->pkey.dsa->p) == 0 &&
240 BN_cmp(a->pkey.dsa->q, b->pkey.dsa->q) == 0 &&
241 BN_cmp(a->pkey.dsa->g, b->pkey.dsa->g) == 0;
242 }
243
dsa_pub_cmp(const EVP_PKEY * a,const EVP_PKEY * b)244 static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
245 return BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) == 0;
246 }
247
int_dsa_free(EVP_PKEY * pkey)248 static void int_dsa_free(EVP_PKEY *pkey) { DSA_free(pkey->pkey.dsa); }
249
250 const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
251 EVP_PKEY_DSA,
252 // 1.2.840.10040.4.1
253 {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01}, 7,
254
255 dsa_pub_decode,
256 dsa_pub_encode,
257 dsa_pub_cmp,
258
259 dsa_priv_decode,
260 dsa_priv_encode,
261
262 NULL /* set_priv_raw */,
263 NULL /* set_pub_raw */,
264 NULL /* get_priv_raw */,
265 NULL /* get_pub_raw */,
266
267 NULL /* pkey_opaque */,
268
269 int_dsa_size,
270 dsa_bits,
271
272 dsa_missing_parameters,
273 dsa_copy_parameters,
274 dsa_cmp_parameters,
275
276 int_dsa_free,
277 };
278