1*cca6fc52SDaniel Fojt /* $OpenBSD: dsa_ameth.c,v 1.28 2019/11/01 15:15:35 jsing Exp $ */ 2f5b1c8a1SJohn Marino /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3f5b1c8a1SJohn Marino * project 2006. 4f5b1c8a1SJohn Marino */ 5f5b1c8a1SJohn Marino /* ==================================================================== 6f5b1c8a1SJohn Marino * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 7f5b1c8a1SJohn Marino * 8f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without 9f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions 10f5b1c8a1SJohn Marino * are met: 11f5b1c8a1SJohn Marino * 12f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the above copyright 13f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer. 14f5b1c8a1SJohn Marino * 15f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright 16f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in 17f5b1c8a1SJohn Marino * the documentation and/or other materials provided with the 18f5b1c8a1SJohn Marino * distribution. 19f5b1c8a1SJohn Marino * 20f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this 21f5b1c8a1SJohn Marino * software must display the following acknowledgment: 22f5b1c8a1SJohn Marino * "This product includes software developed by the OpenSSL Project 23f5b1c8a1SJohn Marino * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24f5b1c8a1SJohn Marino * 25f5b1c8a1SJohn Marino * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26f5b1c8a1SJohn Marino * endorse or promote products derived from this software without 27f5b1c8a1SJohn Marino * prior written permission. For written permission, please contact 28f5b1c8a1SJohn Marino * licensing@OpenSSL.org. 29f5b1c8a1SJohn Marino * 30f5b1c8a1SJohn Marino * 5. Products derived from this software may not be called "OpenSSL" 31f5b1c8a1SJohn Marino * nor may "OpenSSL" appear in their names without prior written 32f5b1c8a1SJohn Marino * permission of the OpenSSL Project. 33f5b1c8a1SJohn Marino * 34f5b1c8a1SJohn Marino * 6. Redistributions of any form whatsoever must retain the following 35f5b1c8a1SJohn Marino * acknowledgment: 36f5b1c8a1SJohn Marino * "This product includes software developed by the OpenSSL Project 37f5b1c8a1SJohn Marino * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38f5b1c8a1SJohn Marino * 39f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40f5b1c8a1SJohn Marino * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42f5b1c8a1SJohn Marino * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43f5b1c8a1SJohn Marino * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44f5b1c8a1SJohn Marino * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45f5b1c8a1SJohn Marino * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46f5b1c8a1SJohn Marino * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48f5b1c8a1SJohn Marino * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49f5b1c8a1SJohn Marino * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50f5b1c8a1SJohn Marino * OF THE POSSIBILITY OF SUCH DAMAGE. 51f5b1c8a1SJohn Marino * ==================================================================== 52f5b1c8a1SJohn Marino * 53f5b1c8a1SJohn Marino * This product includes cryptographic software written by Eric Young 54f5b1c8a1SJohn Marino * (eay@cryptsoft.com). This product includes software written by Tim 55f5b1c8a1SJohn Marino * Hudson (tjh@cryptsoft.com). 56f5b1c8a1SJohn Marino * 57f5b1c8a1SJohn Marino */ 58f5b1c8a1SJohn Marino 59f5b1c8a1SJohn Marino #include <stdio.h> 60f5b1c8a1SJohn Marino 61f5b1c8a1SJohn Marino #include <openssl/opensslconf.h> 62f5b1c8a1SJohn Marino 63f5b1c8a1SJohn Marino #include <openssl/asn1.h> 64f5b1c8a1SJohn Marino #include <openssl/bn.h> 65*cca6fc52SDaniel Fojt #include <openssl/cms.h> 66f5b1c8a1SJohn Marino #include <openssl/dsa.h> 67f5b1c8a1SJohn Marino #include <openssl/err.h> 68f5b1c8a1SJohn Marino #include <openssl/x509.h> 69f5b1c8a1SJohn Marino 70f5b1c8a1SJohn Marino #include "asn1_locl.h" 7172c33676SMaxim Ag #include "bn_lcl.h" 72f5b1c8a1SJohn Marino 73f5b1c8a1SJohn Marino static int 74f5b1c8a1SJohn Marino dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) 75f5b1c8a1SJohn Marino { 76f5b1c8a1SJohn Marino const unsigned char *p, *pm; 77f5b1c8a1SJohn Marino int pklen, pmlen; 78f5b1c8a1SJohn Marino int ptype; 7972c33676SMaxim Ag const void *pval; 8072c33676SMaxim Ag const ASN1_STRING *pstr; 81f5b1c8a1SJohn Marino X509_ALGOR *palg; 82f5b1c8a1SJohn Marino ASN1_INTEGER *public_key = NULL; 83f5b1c8a1SJohn Marino 84f5b1c8a1SJohn Marino DSA *dsa = NULL; 85f5b1c8a1SJohn Marino 86f5b1c8a1SJohn Marino if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) 87f5b1c8a1SJohn Marino return 0; 88f5b1c8a1SJohn Marino X509_ALGOR_get0(NULL, &ptype, &pval, palg); 89f5b1c8a1SJohn Marino 90f5b1c8a1SJohn Marino if (ptype == V_ASN1_SEQUENCE) { 91f5b1c8a1SJohn Marino pstr = pval; 92f5b1c8a1SJohn Marino pm = pstr->data; 93f5b1c8a1SJohn Marino pmlen = pstr->length; 94f5b1c8a1SJohn Marino 95f5b1c8a1SJohn Marino if (!(dsa = d2i_DSAparams(NULL, &pm, pmlen))) { 9672c33676SMaxim Ag DSAerror(DSA_R_DECODE_ERROR); 97f5b1c8a1SJohn Marino goto err; 98f5b1c8a1SJohn Marino } 99f5b1c8a1SJohn Marino } else if (ptype == V_ASN1_NULL || ptype == V_ASN1_UNDEF) { 100f5b1c8a1SJohn Marino if (!(dsa = DSA_new())) { 10172c33676SMaxim Ag DSAerror(ERR_R_MALLOC_FAILURE); 102f5b1c8a1SJohn Marino goto err; 103f5b1c8a1SJohn Marino } 104f5b1c8a1SJohn Marino } else { 10572c33676SMaxim Ag DSAerror(DSA_R_PARAMETER_ENCODING_ERROR); 106f5b1c8a1SJohn Marino goto err; 107f5b1c8a1SJohn Marino } 108f5b1c8a1SJohn Marino 109f5b1c8a1SJohn Marino if (!(public_key=d2i_ASN1_INTEGER(NULL, &p, pklen))) { 11072c33676SMaxim Ag DSAerror(DSA_R_DECODE_ERROR); 111f5b1c8a1SJohn Marino goto err; 112f5b1c8a1SJohn Marino } 113f5b1c8a1SJohn Marino 114f5b1c8a1SJohn Marino if (!(dsa->pub_key = ASN1_INTEGER_to_BN(public_key, NULL))) { 11572c33676SMaxim Ag DSAerror(DSA_R_BN_DECODE_ERROR); 116f5b1c8a1SJohn Marino goto err; 117f5b1c8a1SJohn Marino } 118f5b1c8a1SJohn Marino 119f5b1c8a1SJohn Marino ASN1_INTEGER_free(public_key); 120f5b1c8a1SJohn Marino EVP_PKEY_assign_DSA(pkey, dsa); 121f5b1c8a1SJohn Marino return 1; 122f5b1c8a1SJohn Marino 123f5b1c8a1SJohn Marino err: 124f5b1c8a1SJohn Marino if (public_key) 125f5b1c8a1SJohn Marino ASN1_INTEGER_free(public_key); 126f5b1c8a1SJohn Marino DSA_free(dsa); 127f5b1c8a1SJohn Marino return 0; 128f5b1c8a1SJohn Marino } 129f5b1c8a1SJohn Marino 130f5b1c8a1SJohn Marino static int 131f5b1c8a1SJohn Marino dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) 132f5b1c8a1SJohn Marino { 133f5b1c8a1SJohn Marino DSA *dsa; 134f5b1c8a1SJohn Marino void *pval = NULL; 135f5b1c8a1SJohn Marino int ptype; 136f5b1c8a1SJohn Marino unsigned char *penc = NULL; 137f5b1c8a1SJohn Marino int penclen; 138f5b1c8a1SJohn Marino 139f5b1c8a1SJohn Marino dsa = pkey->pkey.dsa; 140f5b1c8a1SJohn Marino if (pkey->save_parameters && dsa->p && dsa->q && dsa->g) { 141f5b1c8a1SJohn Marino ASN1_STRING *str; 142f5b1c8a1SJohn Marino 143f5b1c8a1SJohn Marino str = ASN1_STRING_new(); 144f5b1c8a1SJohn Marino if (str == NULL) { 14572c33676SMaxim Ag DSAerror(ERR_R_MALLOC_FAILURE); 146f5b1c8a1SJohn Marino goto err; 147f5b1c8a1SJohn Marino } 148f5b1c8a1SJohn Marino str->length = i2d_DSAparams(dsa, &str->data); 149f5b1c8a1SJohn Marino if (str->length <= 0) { 15072c33676SMaxim Ag DSAerror(ERR_R_MALLOC_FAILURE); 151f5b1c8a1SJohn Marino ASN1_STRING_free(str); 152f5b1c8a1SJohn Marino goto err; 153f5b1c8a1SJohn Marino } 154f5b1c8a1SJohn Marino pval = str; 155f5b1c8a1SJohn Marino ptype = V_ASN1_SEQUENCE; 156f5b1c8a1SJohn Marino } else 157f5b1c8a1SJohn Marino ptype = V_ASN1_UNDEF; 158f5b1c8a1SJohn Marino 159f5b1c8a1SJohn Marino dsa->write_params = 0; 160f5b1c8a1SJohn Marino 161f5b1c8a1SJohn Marino penclen = i2d_DSAPublicKey(dsa, &penc); 162f5b1c8a1SJohn Marino 163f5b1c8a1SJohn Marino if (penclen <= 0) { 16472c33676SMaxim Ag DSAerror(ERR_R_MALLOC_FAILURE); 165f5b1c8a1SJohn Marino goto err; 166f5b1c8a1SJohn Marino } 167f5b1c8a1SJohn Marino 168f5b1c8a1SJohn Marino if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_DSA), ptype, pval, 169f5b1c8a1SJohn Marino penc, penclen)) 170f5b1c8a1SJohn Marino return 1; 171f5b1c8a1SJohn Marino 172f5b1c8a1SJohn Marino err: 173f5b1c8a1SJohn Marino free(penc); 174f5b1c8a1SJohn Marino ASN1_STRING_free(pval); 175f5b1c8a1SJohn Marino 176f5b1c8a1SJohn Marino return 0; 177f5b1c8a1SJohn Marino } 178f5b1c8a1SJohn Marino 179f5b1c8a1SJohn Marino /* In PKCS#8 DSA: you just get a private key integer and parameters in the 180f5b1c8a1SJohn Marino * AlgorithmIdentifier the pubkey must be recalculated. 181f5b1c8a1SJohn Marino */ 182f5b1c8a1SJohn Marino static int 18372c33676SMaxim Ag dsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) 184f5b1c8a1SJohn Marino { 185f5b1c8a1SJohn Marino const unsigned char *p, *pm; 186f5b1c8a1SJohn Marino int pklen, pmlen; 187f5b1c8a1SJohn Marino int ptype; 18872c33676SMaxim Ag const void *pval; 18972c33676SMaxim Ag const ASN1_STRING *pstr; 19072c33676SMaxim Ag const X509_ALGOR *palg; 191f5b1c8a1SJohn Marino ASN1_INTEGER *privkey = NULL; 192f5b1c8a1SJohn Marino BN_CTX *ctx = NULL; 193f5b1c8a1SJohn Marino DSA *dsa = NULL; 194f5b1c8a1SJohn Marino 195f5b1c8a1SJohn Marino int ret = 0; 196f5b1c8a1SJohn Marino 197f5b1c8a1SJohn Marino if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) 198f5b1c8a1SJohn Marino return 0; 199f5b1c8a1SJohn Marino X509_ALGOR_get0(NULL, &ptype, &pval, palg); 200f5b1c8a1SJohn Marino if (ptype != V_ASN1_SEQUENCE) 201f5b1c8a1SJohn Marino goto decerr; 202f5b1c8a1SJohn Marino 203f5b1c8a1SJohn Marino if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) 204f5b1c8a1SJohn Marino goto decerr; 205f5b1c8a1SJohn Marino if (privkey->type == V_ASN1_NEG_INTEGER) 206f5b1c8a1SJohn Marino goto decerr; 207f5b1c8a1SJohn Marino 208f5b1c8a1SJohn Marino pstr = pval; 209f5b1c8a1SJohn Marino pm = pstr->data; 210f5b1c8a1SJohn Marino pmlen = pstr->length; 211f5b1c8a1SJohn Marino if (!(dsa = d2i_DSAparams(NULL, &pm, pmlen))) 212f5b1c8a1SJohn Marino goto decerr; 213f5b1c8a1SJohn Marino /* We have parameters now set private key */ 214f5b1c8a1SJohn Marino if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) { 21572c33676SMaxim Ag DSAerror(DSA_R_BN_ERROR); 216f5b1c8a1SJohn Marino goto dsaerr; 217f5b1c8a1SJohn Marino } 218f5b1c8a1SJohn Marino /* Calculate public key */ 219f5b1c8a1SJohn Marino if (!(dsa->pub_key = BN_new())) { 22072c33676SMaxim Ag DSAerror(ERR_R_MALLOC_FAILURE); 221f5b1c8a1SJohn Marino goto dsaerr; 222f5b1c8a1SJohn Marino } 223f5b1c8a1SJohn Marino if (!(ctx = BN_CTX_new())) { 22472c33676SMaxim Ag DSAerror(ERR_R_MALLOC_FAILURE); 225f5b1c8a1SJohn Marino goto dsaerr; 226f5b1c8a1SJohn Marino } 227f5b1c8a1SJohn Marino 22872c33676SMaxim Ag if (!BN_mod_exp_ct(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) { 22972c33676SMaxim Ag DSAerror(DSA_R_BN_ERROR); 230f5b1c8a1SJohn Marino goto dsaerr; 231f5b1c8a1SJohn Marino } 232f5b1c8a1SJohn Marino 233f5b1c8a1SJohn Marino if (!EVP_PKEY_assign_DSA(pkey, dsa)) 234f5b1c8a1SJohn Marino goto decerr; 235f5b1c8a1SJohn Marino 236f5b1c8a1SJohn Marino ret = 1; 237f5b1c8a1SJohn Marino goto done; 238f5b1c8a1SJohn Marino 239f5b1c8a1SJohn Marino decerr: 24072c33676SMaxim Ag DSAerror(DSA_R_DECODE_ERROR); 241f5b1c8a1SJohn Marino dsaerr: 242f5b1c8a1SJohn Marino DSA_free(dsa); 243f5b1c8a1SJohn Marino done: 244f5b1c8a1SJohn Marino BN_CTX_free(ctx); 245f5b1c8a1SJohn Marino ASN1_INTEGER_free(privkey); 246f5b1c8a1SJohn Marino return ret; 247f5b1c8a1SJohn Marino } 248f5b1c8a1SJohn Marino 249f5b1c8a1SJohn Marino static int 250f5b1c8a1SJohn Marino dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) 251f5b1c8a1SJohn Marino { 252f5b1c8a1SJohn Marino ASN1_STRING *params = NULL; 253f5b1c8a1SJohn Marino ASN1_INTEGER *prkey = NULL; 254f5b1c8a1SJohn Marino unsigned char *dp = NULL; 255f5b1c8a1SJohn Marino int dplen; 256f5b1c8a1SJohn Marino 257f5b1c8a1SJohn Marino params = ASN1_STRING_new(); 258f5b1c8a1SJohn Marino if (!params) { 25972c33676SMaxim Ag DSAerror(ERR_R_MALLOC_FAILURE); 260f5b1c8a1SJohn Marino goto err; 261f5b1c8a1SJohn Marino } 262f5b1c8a1SJohn Marino 263f5b1c8a1SJohn Marino params->length = i2d_DSAparams(pkey->pkey.dsa, ¶ms->data); 264f5b1c8a1SJohn Marino if (params->length <= 0) { 26572c33676SMaxim Ag DSAerror(ERR_R_MALLOC_FAILURE); 266f5b1c8a1SJohn Marino goto err; 267f5b1c8a1SJohn Marino } 268f5b1c8a1SJohn Marino params->type = V_ASN1_SEQUENCE; 269f5b1c8a1SJohn Marino 270f5b1c8a1SJohn Marino /* Get private key into integer */ 271f5b1c8a1SJohn Marino prkey = BN_to_ASN1_INTEGER(pkey->pkey.dsa->priv_key, NULL); 272f5b1c8a1SJohn Marino if (!prkey) { 27372c33676SMaxim Ag DSAerror(DSA_R_BN_ERROR); 274f5b1c8a1SJohn Marino goto err; 275f5b1c8a1SJohn Marino } 276f5b1c8a1SJohn Marino 277f5b1c8a1SJohn Marino dplen = i2d_ASN1_INTEGER(prkey, &dp); 278f5b1c8a1SJohn Marino 279f5b1c8a1SJohn Marino ASN1_INTEGER_free(prkey); 280f5b1c8a1SJohn Marino prkey = NULL; 281f5b1c8a1SJohn Marino 282f5b1c8a1SJohn Marino if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_dsa), 0, V_ASN1_SEQUENCE, 283f5b1c8a1SJohn Marino params, dp, dplen)) 284f5b1c8a1SJohn Marino goto err; 285f5b1c8a1SJohn Marino 286f5b1c8a1SJohn Marino return 1; 287f5b1c8a1SJohn Marino 288f5b1c8a1SJohn Marino err: 289f5b1c8a1SJohn Marino free(dp); 290f5b1c8a1SJohn Marino ASN1_STRING_free(params); 291f5b1c8a1SJohn Marino ASN1_INTEGER_free(prkey); 292f5b1c8a1SJohn Marino return 0; 293f5b1c8a1SJohn Marino } 294f5b1c8a1SJohn Marino 295f5b1c8a1SJohn Marino static int 296f5b1c8a1SJohn Marino int_dsa_size(const EVP_PKEY *pkey) 297f5b1c8a1SJohn Marino { 298f5b1c8a1SJohn Marino return DSA_size(pkey->pkey.dsa); 299f5b1c8a1SJohn Marino } 300f5b1c8a1SJohn Marino 301f5b1c8a1SJohn Marino static int 302f5b1c8a1SJohn Marino dsa_bits(const EVP_PKEY *pkey) 303f5b1c8a1SJohn Marino { 304f5b1c8a1SJohn Marino return BN_num_bits(pkey->pkey.dsa->p); 305f5b1c8a1SJohn Marino } 306f5b1c8a1SJohn Marino 307f5b1c8a1SJohn Marino static int 308f5b1c8a1SJohn Marino dsa_missing_parameters(const EVP_PKEY *pkey) 309f5b1c8a1SJohn Marino { 310f5b1c8a1SJohn Marino DSA *dsa; 311f5b1c8a1SJohn Marino 312f5b1c8a1SJohn Marino dsa = pkey->pkey.dsa; 313f5b1c8a1SJohn Marino if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) 314f5b1c8a1SJohn Marino return 1; 315f5b1c8a1SJohn Marino return 0; 316f5b1c8a1SJohn Marino } 317f5b1c8a1SJohn Marino 318f5b1c8a1SJohn Marino static int 319f5b1c8a1SJohn Marino dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) 320f5b1c8a1SJohn Marino { 321f5b1c8a1SJohn Marino BIGNUM *a; 322f5b1c8a1SJohn Marino 323f5b1c8a1SJohn Marino if ((a = BN_dup(from->pkey.dsa->p)) == NULL) 324f5b1c8a1SJohn Marino return 0; 325f5b1c8a1SJohn Marino BN_free(to->pkey.dsa->p); 326f5b1c8a1SJohn Marino to->pkey.dsa->p = a; 327f5b1c8a1SJohn Marino 328f5b1c8a1SJohn Marino if ((a = BN_dup(from->pkey.dsa->q)) == NULL) 329f5b1c8a1SJohn Marino return 0; 330f5b1c8a1SJohn Marino BN_free(to->pkey.dsa->q); 331f5b1c8a1SJohn Marino to->pkey.dsa->q = a; 332f5b1c8a1SJohn Marino 333f5b1c8a1SJohn Marino if ((a = BN_dup(from->pkey.dsa->g)) == NULL) 334f5b1c8a1SJohn Marino return 0; 335f5b1c8a1SJohn Marino BN_free(to->pkey.dsa->g); 336f5b1c8a1SJohn Marino to->pkey.dsa->g = a; 337f5b1c8a1SJohn Marino return 1; 338f5b1c8a1SJohn Marino } 339f5b1c8a1SJohn Marino 340f5b1c8a1SJohn Marino static int 341f5b1c8a1SJohn Marino dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) 342f5b1c8a1SJohn Marino { 343f5b1c8a1SJohn Marino if (BN_cmp(a->pkey.dsa->p, b->pkey.dsa->p) || 344f5b1c8a1SJohn Marino BN_cmp(a->pkey.dsa->q, b->pkey.dsa->q) || 345f5b1c8a1SJohn Marino BN_cmp(a->pkey.dsa->g, b->pkey.dsa->g)) 346f5b1c8a1SJohn Marino return 0; 347f5b1c8a1SJohn Marino else 348f5b1c8a1SJohn Marino return 1; 349f5b1c8a1SJohn Marino } 350f5b1c8a1SJohn Marino 351f5b1c8a1SJohn Marino static int 352f5b1c8a1SJohn Marino dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) 353f5b1c8a1SJohn Marino { 354f5b1c8a1SJohn Marino if (BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) != 0) 355f5b1c8a1SJohn Marino return 0; 356f5b1c8a1SJohn Marino else 357f5b1c8a1SJohn Marino return 1; 358f5b1c8a1SJohn Marino } 359f5b1c8a1SJohn Marino 360f5b1c8a1SJohn Marino static void 361f5b1c8a1SJohn Marino int_dsa_free(EVP_PKEY *pkey) 362f5b1c8a1SJohn Marino { 363f5b1c8a1SJohn Marino DSA_free(pkey->pkey.dsa); 364f5b1c8a1SJohn Marino } 365f5b1c8a1SJohn Marino 366f5b1c8a1SJohn Marino static void 367f5b1c8a1SJohn Marino update_buflen(const BIGNUM *b, size_t *pbuflen) 368f5b1c8a1SJohn Marino { 369f5b1c8a1SJohn Marino size_t i; 370f5b1c8a1SJohn Marino 371f5b1c8a1SJohn Marino if (!b) 372f5b1c8a1SJohn Marino return; 373f5b1c8a1SJohn Marino if (*pbuflen < (i = (size_t)BN_num_bytes(b))) 374f5b1c8a1SJohn Marino *pbuflen = i; 375f5b1c8a1SJohn Marino } 376f5b1c8a1SJohn Marino 377f5b1c8a1SJohn Marino static int 378f5b1c8a1SJohn Marino do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) 379f5b1c8a1SJohn Marino { 380f5b1c8a1SJohn Marino unsigned char *m = NULL; 381f5b1c8a1SJohn Marino int ret = 0; 382f5b1c8a1SJohn Marino size_t buf_len = 0; 383f5b1c8a1SJohn Marino const char *ktype = NULL; 384f5b1c8a1SJohn Marino const BIGNUM *priv_key, *pub_key; 385f5b1c8a1SJohn Marino 386f5b1c8a1SJohn Marino if (ptype == 2) 387f5b1c8a1SJohn Marino priv_key = x->priv_key; 388f5b1c8a1SJohn Marino else 389f5b1c8a1SJohn Marino priv_key = NULL; 390f5b1c8a1SJohn Marino 391f5b1c8a1SJohn Marino if (ptype > 0) 392f5b1c8a1SJohn Marino pub_key = x->pub_key; 393f5b1c8a1SJohn Marino else 394f5b1c8a1SJohn Marino pub_key = NULL; 395f5b1c8a1SJohn Marino 396f5b1c8a1SJohn Marino if (ptype == 2) 397f5b1c8a1SJohn Marino ktype = "Private-Key"; 398f5b1c8a1SJohn Marino else if (ptype == 1) 399f5b1c8a1SJohn Marino ktype = "Public-Key"; 400f5b1c8a1SJohn Marino else 401f5b1c8a1SJohn Marino ktype = "DSA-Parameters"; 402f5b1c8a1SJohn Marino 403f5b1c8a1SJohn Marino update_buflen(x->p, &buf_len); 404f5b1c8a1SJohn Marino update_buflen(x->q, &buf_len); 405f5b1c8a1SJohn Marino update_buflen(x->g, &buf_len); 406f5b1c8a1SJohn Marino update_buflen(priv_key, &buf_len); 407f5b1c8a1SJohn Marino update_buflen(pub_key, &buf_len); 408f5b1c8a1SJohn Marino 409f5b1c8a1SJohn Marino m = malloc(buf_len + 10); 410f5b1c8a1SJohn Marino if (m == NULL) { 41172c33676SMaxim Ag DSAerror(ERR_R_MALLOC_FAILURE); 412f5b1c8a1SJohn Marino goto err; 413f5b1c8a1SJohn Marino } 414f5b1c8a1SJohn Marino 415f5b1c8a1SJohn Marino if (priv_key) { 416f5b1c8a1SJohn Marino if (!BIO_indent(bp, off, 128)) 417f5b1c8a1SJohn Marino goto err; 418f5b1c8a1SJohn Marino if (BIO_printf(bp, "%s: (%d bit)\n", ktype, 419f5b1c8a1SJohn Marino BN_num_bits(x->p)) <= 0) 420f5b1c8a1SJohn Marino goto err; 421f5b1c8a1SJohn Marino } 422f5b1c8a1SJohn Marino 423f5b1c8a1SJohn Marino if (!ASN1_bn_print(bp, "priv:", priv_key, m, off)) 424f5b1c8a1SJohn Marino goto err; 425f5b1c8a1SJohn Marino if (!ASN1_bn_print(bp, "pub: ", pub_key, m, off)) 426f5b1c8a1SJohn Marino goto err; 427f5b1c8a1SJohn Marino if (!ASN1_bn_print(bp, "P: ", x->p, m, off)) 428f5b1c8a1SJohn Marino goto err; 429f5b1c8a1SJohn Marino if (!ASN1_bn_print(bp, "Q: ", x->q, m, off)) 430f5b1c8a1SJohn Marino goto err; 431f5b1c8a1SJohn Marino if (!ASN1_bn_print(bp, "G: ", x->g, m, off)) 432f5b1c8a1SJohn Marino goto err; 433f5b1c8a1SJohn Marino ret = 1; 434f5b1c8a1SJohn Marino err: 435f5b1c8a1SJohn Marino free(m); 436f5b1c8a1SJohn Marino return(ret); 437f5b1c8a1SJohn Marino } 438f5b1c8a1SJohn Marino 439f5b1c8a1SJohn Marino static int 440f5b1c8a1SJohn Marino dsa_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) 441f5b1c8a1SJohn Marino { 442f5b1c8a1SJohn Marino DSA *dsa; 443f5b1c8a1SJohn Marino 444f5b1c8a1SJohn Marino if (!(dsa = d2i_DSAparams(NULL, pder, derlen))) { 44572c33676SMaxim Ag DSAerror(ERR_R_DSA_LIB); 446f5b1c8a1SJohn Marino return 0; 447f5b1c8a1SJohn Marino } 448f5b1c8a1SJohn Marino EVP_PKEY_assign_DSA(pkey, dsa); 449f5b1c8a1SJohn Marino return 1; 450f5b1c8a1SJohn Marino } 451f5b1c8a1SJohn Marino 452f5b1c8a1SJohn Marino static int 453f5b1c8a1SJohn Marino dsa_param_encode(const EVP_PKEY *pkey, unsigned char **pder) 454f5b1c8a1SJohn Marino { 455f5b1c8a1SJohn Marino return i2d_DSAparams(pkey->pkey.dsa, pder); 456f5b1c8a1SJohn Marino } 457f5b1c8a1SJohn Marino 458f5b1c8a1SJohn Marino static int 459f5b1c8a1SJohn Marino dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx) 460f5b1c8a1SJohn Marino { 461f5b1c8a1SJohn Marino return do_dsa_print(bp, pkey->pkey.dsa, indent, 0); 462f5b1c8a1SJohn Marino } 463f5b1c8a1SJohn Marino 464f5b1c8a1SJohn Marino static int 465f5b1c8a1SJohn Marino dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx) 466f5b1c8a1SJohn Marino { 467f5b1c8a1SJohn Marino return do_dsa_print(bp, pkey->pkey.dsa, indent, 1); 468f5b1c8a1SJohn Marino } 469f5b1c8a1SJohn Marino 470f5b1c8a1SJohn Marino static int 471f5b1c8a1SJohn Marino dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx) 472f5b1c8a1SJohn Marino { 473f5b1c8a1SJohn Marino return do_dsa_print(bp, pkey->pkey.dsa, indent, 2); 474f5b1c8a1SJohn Marino } 475f5b1c8a1SJohn Marino 476f5b1c8a1SJohn Marino static int 477f5b1c8a1SJohn Marino old_dsa_priv_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) 478f5b1c8a1SJohn Marino { 479f5b1c8a1SJohn Marino DSA *dsa; 480f5b1c8a1SJohn Marino BN_CTX *ctx = NULL; 481f5b1c8a1SJohn Marino BIGNUM *j, *p1, *newp1; 482f5b1c8a1SJohn Marino 483f5b1c8a1SJohn Marino if (!(dsa = d2i_DSAPrivateKey(NULL, pder, derlen))) { 48472c33676SMaxim Ag DSAerror(ERR_R_DSA_LIB); 485f5b1c8a1SJohn Marino return 0; 486f5b1c8a1SJohn Marino } 487f5b1c8a1SJohn Marino 488f5b1c8a1SJohn Marino ctx = BN_CTX_new(); 489f5b1c8a1SJohn Marino if (ctx == NULL) 490f5b1c8a1SJohn Marino goto err; 491f5b1c8a1SJohn Marino 492f5b1c8a1SJohn Marino /* 493f5b1c8a1SJohn Marino * Check that p and q are consistent with each other. 494f5b1c8a1SJohn Marino */ 495f5b1c8a1SJohn Marino 496f5b1c8a1SJohn Marino j = BN_CTX_get(ctx); 497f5b1c8a1SJohn Marino p1 = BN_CTX_get(ctx); 498f5b1c8a1SJohn Marino newp1 = BN_CTX_get(ctx); 499f5b1c8a1SJohn Marino if (j == NULL || p1 == NULL || newp1 == NULL) 500f5b1c8a1SJohn Marino goto err; 501f5b1c8a1SJohn Marino /* p1 = p - 1 */ 502f5b1c8a1SJohn Marino if (BN_sub(p1, dsa->p, BN_value_one()) == 0) 503f5b1c8a1SJohn Marino goto err; 504f5b1c8a1SJohn Marino /* j = (p - 1) / q */ 50572c33676SMaxim Ag if (BN_div_ct(j, NULL, p1, dsa->q, ctx) == 0) 506f5b1c8a1SJohn Marino goto err; 507f5b1c8a1SJohn Marino /* q * j should == p - 1 */ 508f5b1c8a1SJohn Marino if (BN_mul(newp1, dsa->q, j, ctx) == 0) 509f5b1c8a1SJohn Marino goto err; 510f5b1c8a1SJohn Marino if (BN_cmp(newp1, p1) != 0) { 51172c33676SMaxim Ag DSAerror(DSA_R_BAD_Q_VALUE); 512f5b1c8a1SJohn Marino goto err; 513f5b1c8a1SJohn Marino } 514f5b1c8a1SJohn Marino 515f5b1c8a1SJohn Marino /* 516f5b1c8a1SJohn Marino * Check that q is not a composite number. 517f5b1c8a1SJohn Marino */ 518f5b1c8a1SJohn Marino 51972c33676SMaxim Ag if (BN_is_prime_ex(dsa->q, BN_prime_checks, ctx, NULL) <= 0) { 52072c33676SMaxim Ag DSAerror(DSA_R_BAD_Q_VALUE); 521f5b1c8a1SJohn Marino goto err; 522f5b1c8a1SJohn Marino } 523f5b1c8a1SJohn Marino 524f5b1c8a1SJohn Marino BN_CTX_free(ctx); 525f5b1c8a1SJohn Marino 526f5b1c8a1SJohn Marino EVP_PKEY_assign_DSA(pkey, dsa); 527f5b1c8a1SJohn Marino return 1; 528f5b1c8a1SJohn Marino 529f5b1c8a1SJohn Marino err: 530f5b1c8a1SJohn Marino BN_CTX_free(ctx); 531f5b1c8a1SJohn Marino DSA_free(dsa); 532f5b1c8a1SJohn Marino return 0; 533f5b1c8a1SJohn Marino } 534f5b1c8a1SJohn Marino 535f5b1c8a1SJohn Marino static int 536f5b1c8a1SJohn Marino old_dsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder) 537f5b1c8a1SJohn Marino { 538f5b1c8a1SJohn Marino return i2d_DSAPrivateKey(pkey->pkey.dsa, pder); 539f5b1c8a1SJohn Marino } 540f5b1c8a1SJohn Marino 541f5b1c8a1SJohn Marino static int 542f5b1c8a1SJohn Marino dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg, const ASN1_STRING *sig, 543f5b1c8a1SJohn Marino int indent, ASN1_PCTX *pctx) 544f5b1c8a1SJohn Marino { 545f5b1c8a1SJohn Marino DSA_SIG *dsa_sig; 546f5b1c8a1SJohn Marino const unsigned char *p; 547f5b1c8a1SJohn Marino 548f5b1c8a1SJohn Marino if (!sig) { 549f5b1c8a1SJohn Marino if (BIO_puts(bp, "\n") <= 0) 550f5b1c8a1SJohn Marino return 0; 551f5b1c8a1SJohn Marino else 552f5b1c8a1SJohn Marino return 1; 553f5b1c8a1SJohn Marino } 554f5b1c8a1SJohn Marino p = sig->data; 555f5b1c8a1SJohn Marino dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length); 556f5b1c8a1SJohn Marino if (dsa_sig) { 557f5b1c8a1SJohn Marino int rv = 0; 558f5b1c8a1SJohn Marino size_t buf_len = 0; 559f5b1c8a1SJohn Marino unsigned char *m = NULL; 560f5b1c8a1SJohn Marino 561f5b1c8a1SJohn Marino update_buflen(dsa_sig->r, &buf_len); 562f5b1c8a1SJohn Marino update_buflen(dsa_sig->s, &buf_len); 563f5b1c8a1SJohn Marino m = malloc(buf_len + 10); 564f5b1c8a1SJohn Marino if (m == NULL) { 56572c33676SMaxim Ag DSAerror(ERR_R_MALLOC_FAILURE); 566f5b1c8a1SJohn Marino goto err; 567f5b1c8a1SJohn Marino } 568f5b1c8a1SJohn Marino 569f5b1c8a1SJohn Marino if (BIO_write(bp, "\n", 1) != 1) 570f5b1c8a1SJohn Marino goto err; 571f5b1c8a1SJohn Marino 572f5b1c8a1SJohn Marino if (!ASN1_bn_print(bp, "r: ", dsa_sig->r, m, indent)) 573f5b1c8a1SJohn Marino goto err; 574f5b1c8a1SJohn Marino if (!ASN1_bn_print(bp, "s: ", dsa_sig->s, m, indent)) 575f5b1c8a1SJohn Marino goto err; 576f5b1c8a1SJohn Marino rv = 1; 577f5b1c8a1SJohn Marino err: 578f5b1c8a1SJohn Marino free(m); 579f5b1c8a1SJohn Marino DSA_SIG_free(dsa_sig); 580f5b1c8a1SJohn Marino return rv; 581f5b1c8a1SJohn Marino } 582f5b1c8a1SJohn Marino return X509_signature_dump(bp, sig, indent); 583f5b1c8a1SJohn Marino } 584f5b1c8a1SJohn Marino 585f5b1c8a1SJohn Marino static int 586f5b1c8a1SJohn Marino dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) 587f5b1c8a1SJohn Marino { 588f5b1c8a1SJohn Marino switch (op) { 589f5b1c8a1SJohn Marino case ASN1_PKEY_CTRL_PKCS7_SIGN: 590f5b1c8a1SJohn Marino if (arg1 == 0) { 591f5b1c8a1SJohn Marino int snid, hnid; 592f5b1c8a1SJohn Marino X509_ALGOR *alg1, *alg2; 593f5b1c8a1SJohn Marino 594f5b1c8a1SJohn Marino PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2); 595f5b1c8a1SJohn Marino if (alg1 == NULL || alg1->algorithm == NULL) 596f5b1c8a1SJohn Marino return -1; 597f5b1c8a1SJohn Marino hnid = OBJ_obj2nid(alg1->algorithm); 598f5b1c8a1SJohn Marino if (hnid == NID_undef) 599f5b1c8a1SJohn Marino return -1; 600f5b1c8a1SJohn Marino if (!OBJ_find_sigid_by_algs(&snid, hnid, 601f5b1c8a1SJohn Marino EVP_PKEY_id(pkey))) 602f5b1c8a1SJohn Marino return -1; 603f5b1c8a1SJohn Marino X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 604f5b1c8a1SJohn Marino 0); 605f5b1c8a1SJohn Marino } 606f5b1c8a1SJohn Marino return 1; 607f5b1c8a1SJohn Marino 608*cca6fc52SDaniel Fojt #ifndef OPENSSL_NO_CMS 609*cca6fc52SDaniel Fojt case ASN1_PKEY_CTRL_CMS_SIGN: 610*cca6fc52SDaniel Fojt if (arg1 == 0) { 611*cca6fc52SDaniel Fojt int snid, hnid; 612*cca6fc52SDaniel Fojt X509_ALGOR *alg1, *alg2; 613*cca6fc52SDaniel Fojt 614*cca6fc52SDaniel Fojt CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2); 615*cca6fc52SDaniel Fojt if (alg1 == NULL || alg1->algorithm == NULL) 616*cca6fc52SDaniel Fojt return -1; 617*cca6fc52SDaniel Fojt hnid = OBJ_obj2nid(alg1->algorithm); 618*cca6fc52SDaniel Fojt if (hnid == NID_undef) 619*cca6fc52SDaniel Fojt return -1; 620*cca6fc52SDaniel Fojt if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) 621*cca6fc52SDaniel Fojt return -1; 622*cca6fc52SDaniel Fojt X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); 623*cca6fc52SDaniel Fojt } 624*cca6fc52SDaniel Fojt return 1; 625*cca6fc52SDaniel Fojt 626*cca6fc52SDaniel Fojt case ASN1_PKEY_CTRL_CMS_RI_TYPE: 627*cca6fc52SDaniel Fojt *(int *)arg2 = CMS_RECIPINFO_NONE; 628*cca6fc52SDaniel Fojt return 1; 629*cca6fc52SDaniel Fojt #endif 630*cca6fc52SDaniel Fojt 631f5b1c8a1SJohn Marino case ASN1_PKEY_CTRL_DEFAULT_MD_NID: 632f5b1c8a1SJohn Marino *(int *)arg2 = NID_sha1; 633f5b1c8a1SJohn Marino return 2; 634f5b1c8a1SJohn Marino 635f5b1c8a1SJohn Marino default: 636f5b1c8a1SJohn Marino return -2; 637f5b1c8a1SJohn Marino } 638f5b1c8a1SJohn Marino } 639f5b1c8a1SJohn Marino 640f5b1c8a1SJohn Marino /* NB these are sorted in pkey_id order, lowest first */ 641f5b1c8a1SJohn Marino 642f5b1c8a1SJohn Marino const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] = { 643f5b1c8a1SJohn Marino { 644f5b1c8a1SJohn Marino .pkey_id = EVP_PKEY_DSA2, 645f5b1c8a1SJohn Marino .pkey_base_id = EVP_PKEY_DSA, 646f5b1c8a1SJohn Marino .pkey_flags = ASN1_PKEY_ALIAS 647f5b1c8a1SJohn Marino }, 648f5b1c8a1SJohn Marino 649f5b1c8a1SJohn Marino { 650f5b1c8a1SJohn Marino .pkey_id = EVP_PKEY_DSA1, 651f5b1c8a1SJohn Marino .pkey_base_id = EVP_PKEY_DSA, 652f5b1c8a1SJohn Marino .pkey_flags = ASN1_PKEY_ALIAS 653f5b1c8a1SJohn Marino }, 654f5b1c8a1SJohn Marino 655f5b1c8a1SJohn Marino { 656f5b1c8a1SJohn Marino .pkey_id = EVP_PKEY_DSA4, 657f5b1c8a1SJohn Marino .pkey_base_id = EVP_PKEY_DSA, 658f5b1c8a1SJohn Marino .pkey_flags = ASN1_PKEY_ALIAS 659f5b1c8a1SJohn Marino }, 660f5b1c8a1SJohn Marino 661f5b1c8a1SJohn Marino { 662f5b1c8a1SJohn Marino .pkey_id = EVP_PKEY_DSA3, 663f5b1c8a1SJohn Marino .pkey_base_id = EVP_PKEY_DSA, 664f5b1c8a1SJohn Marino .pkey_flags = ASN1_PKEY_ALIAS 665f5b1c8a1SJohn Marino }, 666f5b1c8a1SJohn Marino 667f5b1c8a1SJohn Marino { 668f5b1c8a1SJohn Marino .pkey_id = EVP_PKEY_DSA, 669f5b1c8a1SJohn Marino .pkey_base_id = EVP_PKEY_DSA, 670f5b1c8a1SJohn Marino 671f5b1c8a1SJohn Marino .pem_str = "DSA", 672f5b1c8a1SJohn Marino .info = "OpenSSL DSA method", 673f5b1c8a1SJohn Marino 674f5b1c8a1SJohn Marino .pub_decode = dsa_pub_decode, 675f5b1c8a1SJohn Marino .pub_encode = dsa_pub_encode, 676f5b1c8a1SJohn Marino .pub_cmp = dsa_pub_cmp, 677f5b1c8a1SJohn Marino .pub_print = dsa_pub_print, 678f5b1c8a1SJohn Marino 679f5b1c8a1SJohn Marino .priv_decode = dsa_priv_decode, 680f5b1c8a1SJohn Marino .priv_encode = dsa_priv_encode, 681f5b1c8a1SJohn Marino .priv_print = dsa_priv_print, 682f5b1c8a1SJohn Marino 683f5b1c8a1SJohn Marino .pkey_size = int_dsa_size, 684f5b1c8a1SJohn Marino .pkey_bits = dsa_bits, 685f5b1c8a1SJohn Marino 686f5b1c8a1SJohn Marino .param_decode = dsa_param_decode, 687f5b1c8a1SJohn Marino .param_encode = dsa_param_encode, 688f5b1c8a1SJohn Marino .param_missing = dsa_missing_parameters, 689f5b1c8a1SJohn Marino .param_copy = dsa_copy_parameters, 690f5b1c8a1SJohn Marino .param_cmp = dsa_cmp_parameters, 691f5b1c8a1SJohn Marino .param_print = dsa_param_print, 692f5b1c8a1SJohn Marino .sig_print = dsa_sig_print, 693f5b1c8a1SJohn Marino 694f5b1c8a1SJohn Marino .pkey_free = int_dsa_free, 695f5b1c8a1SJohn Marino .pkey_ctrl = dsa_pkey_ctrl, 696f5b1c8a1SJohn Marino .old_priv_decode = old_dsa_priv_decode, 697f5b1c8a1SJohn Marino .old_priv_encode = old_dsa_priv_encode 698f5b1c8a1SJohn Marino } 699f5b1c8a1SJohn Marino }; 700