Home | History | Annotate | Download | only in evp
      1 /* Written by Dr Stephen N Henson (steve (at) 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 (at) 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 (at) cryptsoft.com).  This product includes software written by Tim
     54  * Hudson (tjh (at) 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 
     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 
    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 
    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 
    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 
    194 static int int_dsa_size(const EVP_PKEY *pkey) {
    195   return DSA_size(pkey->pkey.dsa);
    196 }
    197 
    198 static int dsa_bits(const EVP_PKEY *pkey) {
    199   return BN_num_bits(pkey->pkey.dsa->p);
    200 }
    201 
    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 
    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 
    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 
    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 
    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 
    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 /* 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