• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
145   if (!BN_parse_asn1_unsigned(key, dsa->priv_key) ||
146       CBS_len(key) != 0) {
147     OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
148     goto err;
149   }
150 
151   // Calculate the public key.
152   ctx = BN_CTX_new();
153   if (ctx == NULL ||
154       !BN_mod_exp_mont_consttime(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p,
155                                  ctx, NULL)) {
156     goto err;
157   }
158 
159   BN_CTX_free(ctx);
160   EVP_PKEY_assign_DSA(out, dsa);
161   return 1;
162 
163 err:
164   BN_CTX_free(ctx);
165   DSA_free(dsa);
166   return 0;
167 }
168 
dsa_priv_encode(CBB * out,const EVP_PKEY * key)169 static int dsa_priv_encode(CBB *out, const EVP_PKEY *key) {
170   const DSA *dsa = key->pkey.dsa;
171   if (dsa == NULL || dsa->priv_key == NULL) {
172     OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
173     return 0;
174   }
175 
176   // See PKCS#11, v2.40, section 2.5.
177   CBB pkcs8, algorithm, oid, private_key;
178   if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
179       !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
180       !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
181       !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
182       !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
183       !DSA_marshal_parameters(&algorithm, dsa) ||
184       !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
185       !BN_marshal_asn1(&private_key, dsa->priv_key) ||
186       !CBB_flush(out)) {
187     OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
188     return 0;
189   }
190 
191   return 1;
192 }
193 
int_dsa_size(const EVP_PKEY * pkey)194 static int int_dsa_size(const EVP_PKEY *pkey) {
195   return DSA_size(pkey->pkey.dsa);
196 }
197 
dsa_bits(const EVP_PKEY * pkey)198 static int dsa_bits(const EVP_PKEY *pkey) {
199   return BN_num_bits(pkey->pkey.dsa->p);
200 }
201 
dsa_missing_parameters(const EVP_PKEY * pkey)202 static int dsa_missing_parameters(const EVP_PKEY *pkey) {
203   DSA *dsa;
204   dsa = pkey->pkey.dsa;
205   if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
206     return 1;
207   }
208   return 0;
209 }
210 
dup_bn_into(BIGNUM ** out,BIGNUM * src)211 static int dup_bn_into(BIGNUM **out, BIGNUM *src) {
212   BIGNUM *a;
213 
214   a = BN_dup(src);
215   if (a == NULL) {
216     return 0;
217   }
218   BN_free(*out);
219   *out = a;
220 
221   return 1;
222 }
223 
dsa_copy_parameters(EVP_PKEY * to,const EVP_PKEY * from)224 static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
225   if (!dup_bn_into(&to->pkey.dsa->p, from->pkey.dsa->p) ||
226       !dup_bn_into(&to->pkey.dsa->q, from->pkey.dsa->q) ||
227       !dup_bn_into(&to->pkey.dsa->g, from->pkey.dsa->g)) {
228     return 0;
229   }
230 
231   return 1;
232 }
233 
dsa_cmp_parameters(const EVP_PKEY * a,const EVP_PKEY * b)234 static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
235   return BN_cmp(a->pkey.dsa->p, b->pkey.dsa->p) == 0 &&
236          BN_cmp(a->pkey.dsa->q, b->pkey.dsa->q) == 0 &&
237          BN_cmp(a->pkey.dsa->g, b->pkey.dsa->g) == 0;
238 }
239 
dsa_pub_cmp(const EVP_PKEY * a,const EVP_PKEY * b)240 static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
241   return BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) == 0;
242 }
243 
int_dsa_free(EVP_PKEY * pkey)244 static void int_dsa_free(EVP_PKEY *pkey) { DSA_free(pkey->pkey.dsa); }
245 
246 const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
247   EVP_PKEY_DSA,
248   // 1.2.840.10040.4.1
249   {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01}, 7,
250 
251   dsa_pub_decode,
252   dsa_pub_encode,
253   dsa_pub_cmp,
254 
255   dsa_priv_decode,
256   dsa_priv_encode,
257 
258   NULL /* set_priv_raw */,
259   NULL /* set_pub_raw */,
260   NULL /* get_priv_raw */,
261   NULL /* get_pub_raw */,
262 
263   NULL /* pkey_opaque */,
264 
265   int_dsa_size,
266   dsa_bits,
267 
268   dsa_missing_parameters,
269   dsa_copy_parameters,
270   dsa_cmp_parameters,
271 
272   int_dsa_free,
273 };
274