1280304Sjkim/* 2280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 3280304Sjkim * 2006. 4238384Sjkim */ 5238384Sjkim/* ==================================================================== 6238384Sjkim * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 7238384Sjkim * 8238384Sjkim * Redistribution and use in source and binary forms, with or without 9238384Sjkim * modification, are permitted provided that the following conditions 10238384Sjkim * are met: 11238384Sjkim * 12238384Sjkim * 1. Redistributions of source code must retain the above copyright 13280304Sjkim * notice, this list of conditions and the following disclaimer. 14238384Sjkim * 15238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 16238384Sjkim * notice, this list of conditions and the following disclaimer in 17238384Sjkim * the documentation and/or other materials provided with the 18238384Sjkim * distribution. 19238384Sjkim * 20238384Sjkim * 3. All advertising materials mentioning features or use of this 21238384Sjkim * software must display the following acknowledgment: 22238384Sjkim * "This product includes software developed by the OpenSSL Project 23238384Sjkim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24238384Sjkim * 25238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26238384Sjkim * endorse or promote products derived from this software without 27238384Sjkim * prior written permission. For written permission, please contact 28238384Sjkim * licensing@OpenSSL.org. 29238384Sjkim * 30238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 31238384Sjkim * nor may "OpenSSL" appear in their names without prior written 32238384Sjkim * permission of the OpenSSL Project. 33238384Sjkim * 34238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 35238384Sjkim * acknowledgment: 36238384Sjkim * "This product includes software developed by the OpenSSL Project 37238384Sjkim * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38238384Sjkim * 39238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 51238384Sjkim * ==================================================================== 52238384Sjkim * 53238384Sjkim * This product includes cryptographic software written by Eric Young 54238384Sjkim * (eay@cryptsoft.com). This product includes software written by Tim 55238384Sjkim * Hudson (tjh@cryptsoft.com). 56238384Sjkim * 57238384Sjkim */ 58238384Sjkim 59238384Sjkim#include <stdio.h> 60238384Sjkim#include "cryptlib.h" 61238384Sjkim#include <openssl/asn1t.h> 62238384Sjkim#include <openssl/x509.h> 63238384Sjkim#include <openssl/evp.h> 64238384Sjkim#include <openssl/bn.h> 65238384Sjkim#include "evp_locl.h" 66238384Sjkim#include "dsa_locl.h" 67238384Sjkim 68238384Sjkim/* DSA pkey context structure */ 69238384Sjkim 70280304Sjkimtypedef struct { 71280304Sjkim /* Parameter gen parameters */ 72280304Sjkim int nbits; /* size of p in bits (default: 1024) */ 73280304Sjkim int qbits; /* size of q in bits (default: 160) */ 74280304Sjkim const EVP_MD *pmd; /* MD for parameter generation */ 75280304Sjkim /* Keygen callback info */ 76280304Sjkim int gentmp[2]; 77280304Sjkim /* message digest */ 78280304Sjkim const EVP_MD *md; /* MD for the signature */ 79280304Sjkim} DSA_PKEY_CTX; 80238384Sjkim 81238384Sjkimstatic int pkey_dsa_init(EVP_PKEY_CTX *ctx) 82280304Sjkim{ 83280304Sjkim DSA_PKEY_CTX *dctx; 84280304Sjkim dctx = OPENSSL_malloc(sizeof(DSA_PKEY_CTX)); 85280304Sjkim if (!dctx) 86280304Sjkim return 0; 87280304Sjkim dctx->nbits = 1024; 88280304Sjkim dctx->qbits = 160; 89280304Sjkim dctx->pmd = NULL; 90280304Sjkim dctx->md = NULL; 91238384Sjkim 92280304Sjkim ctx->data = dctx; 93280304Sjkim ctx->keygen_info = dctx->gentmp; 94280304Sjkim ctx->keygen_info_count = 2; 95238384Sjkim 96280304Sjkim return 1; 97280304Sjkim} 98280304Sjkim 99238384Sjkimstatic int pkey_dsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 100280304Sjkim{ 101280304Sjkim DSA_PKEY_CTX *dctx, *sctx; 102280304Sjkim if (!pkey_dsa_init(dst)) 103280304Sjkim return 0; 104280304Sjkim sctx = src->data; 105280304Sjkim dctx = dst->data; 106280304Sjkim dctx->nbits = sctx->nbits; 107280304Sjkim dctx->qbits = sctx->qbits; 108280304Sjkim dctx->pmd = sctx->pmd; 109280304Sjkim dctx->md = sctx->md; 110280304Sjkim return 1; 111280304Sjkim} 112238384Sjkim 113238384Sjkimstatic void pkey_dsa_cleanup(EVP_PKEY_CTX *ctx) 114280304Sjkim{ 115280304Sjkim DSA_PKEY_CTX *dctx = ctx->data; 116280304Sjkim if (dctx) 117280304Sjkim OPENSSL_free(dctx); 118280304Sjkim} 119238384Sjkim 120280304Sjkimstatic int pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, 121280304Sjkim size_t *siglen, const unsigned char *tbs, 122280304Sjkim size_t tbslen) 123280304Sjkim{ 124280304Sjkim int ret, type; 125280304Sjkim unsigned int sltmp; 126280304Sjkim DSA_PKEY_CTX *dctx = ctx->data; 127280304Sjkim DSA *dsa = ctx->pkey->pkey.dsa; 128238384Sjkim 129280304Sjkim if (dctx->md) 130280304Sjkim type = EVP_MD_type(dctx->md); 131280304Sjkim else 132280304Sjkim type = NID_sha1; 133238384Sjkim 134280304Sjkim ret = DSA_sign(type, tbs, tbslen, sig, &sltmp, dsa); 135238384Sjkim 136280304Sjkim if (ret <= 0) 137280304Sjkim return ret; 138280304Sjkim *siglen = sltmp; 139280304Sjkim return 1; 140280304Sjkim} 141238384Sjkim 142238384Sjkimstatic int pkey_dsa_verify(EVP_PKEY_CTX *ctx, 143280304Sjkim const unsigned char *sig, size_t siglen, 144280304Sjkim const unsigned char *tbs, size_t tbslen) 145280304Sjkim{ 146280304Sjkim int ret, type; 147280304Sjkim DSA_PKEY_CTX *dctx = ctx->data; 148280304Sjkim DSA *dsa = ctx->pkey->pkey.dsa; 149238384Sjkim 150280304Sjkim if (dctx->md) 151280304Sjkim type = EVP_MD_type(dctx->md); 152280304Sjkim else 153280304Sjkim type = NID_sha1; 154238384Sjkim 155280304Sjkim ret = DSA_verify(type, tbs, tbslen, sig, siglen, dsa); 156238384Sjkim 157280304Sjkim return ret; 158280304Sjkim} 159238384Sjkim 160238384Sjkimstatic int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 161280304Sjkim{ 162280304Sjkim DSA_PKEY_CTX *dctx = ctx->data; 163280304Sjkim switch (type) { 164280304Sjkim case EVP_PKEY_CTRL_DSA_PARAMGEN_BITS: 165280304Sjkim if (p1 < 256) 166280304Sjkim return -2; 167280304Sjkim dctx->nbits = p1; 168280304Sjkim return 1; 169238384Sjkim 170280304Sjkim case EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS: 171280304Sjkim if (p1 != 160 && p1 != 224 && p1 && p1 != 256) 172280304Sjkim return -2; 173280304Sjkim dctx->qbits = p1; 174280304Sjkim return 1; 175238384Sjkim 176280304Sjkim case EVP_PKEY_CTRL_DSA_PARAMGEN_MD: 177280304Sjkim if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && 178280304Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && 179280304Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_sha256) { 180280304Sjkim DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE); 181280304Sjkim return 0; 182280304Sjkim } 183280304Sjkim dctx->md = p2; 184280304Sjkim return 1; 185238384Sjkim 186280304Sjkim case EVP_PKEY_CTRL_MD: 187280304Sjkim if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && 188280304Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_dsa && 189280304Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_dsaWithSHA && 190280304Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && 191280304Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && 192280304Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && 193280304Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_sha512) { 194280304Sjkim DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE); 195280304Sjkim return 0; 196280304Sjkim } 197280304Sjkim dctx->md = p2; 198280304Sjkim return 1; 199238384Sjkim 200280304Sjkim case EVP_PKEY_CTRL_DIGESTINIT: 201280304Sjkim case EVP_PKEY_CTRL_PKCS7_SIGN: 202280304Sjkim case EVP_PKEY_CTRL_CMS_SIGN: 203280304Sjkim return 1; 204238384Sjkim 205280304Sjkim case EVP_PKEY_CTRL_PEER_KEY: 206280304Sjkim DSAerr(DSA_F_PKEY_DSA_CTRL, 207280304Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 208280304Sjkim return -2; 209280304Sjkim default: 210280304Sjkim return -2; 211280304Sjkim 212280304Sjkim } 213280304Sjkim} 214280304Sjkim 215238384Sjkimstatic int pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx, 216280304Sjkim const char *type, const char *value) 217280304Sjkim{ 218280304Sjkim if (!strcmp(type, "dsa_paramgen_bits")) { 219280304Sjkim int nbits; 220280304Sjkim nbits = atoi(value); 221280304Sjkim return EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits); 222280304Sjkim } 223280304Sjkim if (!strcmp(type, "dsa_paramgen_q_bits")) { 224280304Sjkim int qbits = atoi(value); 225280304Sjkim return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, 226280304Sjkim EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, qbits, 227280304Sjkim NULL); 228280304Sjkim } 229280304Sjkim if (!strcmp(type, "dsa_paramgen_md")) { 230280304Sjkim return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, 231280304Sjkim EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0, 232280304Sjkim (void *)EVP_get_digestbyname(value)); 233280304Sjkim } 234280304Sjkim return -2; 235280304Sjkim} 236238384Sjkim 237238384Sjkimstatic int pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 238280304Sjkim{ 239280304Sjkim DSA *dsa = NULL; 240280304Sjkim DSA_PKEY_CTX *dctx = ctx->data; 241280304Sjkim BN_GENCB *pcb, cb; 242280304Sjkim int ret; 243280304Sjkim if (ctx->pkey_gencb) { 244280304Sjkim pcb = &cb; 245280304Sjkim evp_pkey_set_cb_translate(pcb, ctx); 246280304Sjkim } else 247280304Sjkim pcb = NULL; 248280304Sjkim dsa = DSA_new(); 249280304Sjkim if (!dsa) 250280304Sjkim return 0; 251280304Sjkim ret = dsa_builtin_paramgen(dsa, dctx->nbits, dctx->qbits, dctx->pmd, 252280304Sjkim NULL, 0, NULL, NULL, NULL, pcb); 253280304Sjkim if (ret) 254280304Sjkim EVP_PKEY_assign_DSA(pkey, dsa); 255280304Sjkim else 256280304Sjkim DSA_free(dsa); 257280304Sjkim return ret; 258280304Sjkim} 259238384Sjkim 260238384Sjkimstatic int pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 261280304Sjkim{ 262280304Sjkim DSA *dsa = NULL; 263280304Sjkim if (ctx->pkey == NULL) { 264280304Sjkim DSAerr(DSA_F_PKEY_DSA_KEYGEN, DSA_R_NO_PARAMETERS_SET); 265280304Sjkim return 0; 266280304Sjkim } 267280304Sjkim dsa = DSA_new(); 268280304Sjkim if (!dsa) 269280304Sjkim return 0; 270280304Sjkim EVP_PKEY_assign_DSA(pkey, dsa); 271280304Sjkim /* Note: if error return, pkey is freed by parent routine */ 272280304Sjkim if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) 273280304Sjkim return 0; 274280304Sjkim return DSA_generate_key(pkey->pkey.dsa); 275280304Sjkim} 276238384Sjkim 277280304Sjkimconst EVP_PKEY_METHOD dsa_pkey_meth = { 278280304Sjkim EVP_PKEY_DSA, 279280304Sjkim EVP_PKEY_FLAG_AUTOARGLEN, 280280304Sjkim pkey_dsa_init, 281280304Sjkim pkey_dsa_copy, 282280304Sjkim pkey_dsa_cleanup, 283238384Sjkim 284280304Sjkim 0, 285280304Sjkim pkey_dsa_paramgen, 286238384Sjkim 287280304Sjkim 0, 288280304Sjkim pkey_dsa_keygen, 289238384Sjkim 290280304Sjkim 0, 291280304Sjkim pkey_dsa_sign, 292238384Sjkim 293280304Sjkim 0, 294280304Sjkim pkey_dsa_verify, 295238384Sjkim 296280304Sjkim 0, 0, 297238384Sjkim 298280304Sjkim 0, 0, 0, 0, 299238384Sjkim 300280304Sjkim 0, 0, 301238384Sjkim 302280304Sjkim 0, 0, 303238384Sjkim 304280304Sjkim 0, 0, 305238384Sjkim 306280304Sjkim pkey_dsa_ctrl, 307280304Sjkim pkey_dsa_ctrl_str 308280304Sjkim}; 309