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 67static 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 99err: 100 DSA_free(dsa); 101 return 0; 102} 103 104static 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 127static 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 163err: 164 BN_CTX_free(ctx); 165 DSA_free(dsa); 166 return 0; 167} 168 169static 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 194static int int_dsa_size(const EVP_PKEY *pkey) { 195 return DSA_size(pkey->pkey.dsa); 196} 197 198static int dsa_bits(const EVP_PKEY *pkey) { 199 return BN_num_bits(pkey->pkey.dsa->p); 200} 201 202static 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 211static 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 224static 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 234static 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 240static 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 244static void int_dsa_free(EVP_PKEY *pkey) { DSA_free(pkey->pkey.dsa); } 245 246const 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 /* pkey_opaque */, 259 260 int_dsa_size, 261 dsa_bits, 262 263 dsa_missing_parameters, 264 dsa_copy_parameters, 265 dsa_cmp_parameters, 266 267 int_dsa_free, 268}; 269