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/dh.h> 65238384Sjkim#include <openssl/bn.h> 66238384Sjkim#include "evp_locl.h" 67238384Sjkim 68238384Sjkim/* DH pkey context structure */ 69238384Sjkim 70280304Sjkimtypedef struct { 71280304Sjkim /* Parameter gen parameters */ 72280304Sjkim int prime_len; 73280304Sjkim int generator; 74280304Sjkim int use_dsa; 75280304Sjkim /* Keygen callback info */ 76280304Sjkim int gentmp[2]; 77280304Sjkim /* message digest */ 78280304Sjkim} DH_PKEY_CTX; 79238384Sjkim 80238384Sjkimstatic int pkey_dh_init(EVP_PKEY_CTX *ctx) 81280304Sjkim{ 82280304Sjkim DH_PKEY_CTX *dctx; 83280304Sjkim dctx = OPENSSL_malloc(sizeof(DH_PKEY_CTX)); 84280304Sjkim if (!dctx) 85280304Sjkim return 0; 86280304Sjkim dctx->prime_len = 1024; 87280304Sjkim dctx->generator = 2; 88280304Sjkim dctx->use_dsa = 0; 89238384Sjkim 90280304Sjkim ctx->data = dctx; 91280304Sjkim ctx->keygen_info = dctx->gentmp; 92280304Sjkim ctx->keygen_info_count = 2; 93238384Sjkim 94280304Sjkim return 1; 95280304Sjkim} 96280304Sjkim 97238384Sjkimstatic int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 98280304Sjkim{ 99280304Sjkim DH_PKEY_CTX *dctx, *sctx; 100280304Sjkim if (!pkey_dh_init(dst)) 101280304Sjkim return 0; 102280304Sjkim sctx = src->data; 103280304Sjkim dctx = dst->data; 104280304Sjkim dctx->prime_len = sctx->prime_len; 105280304Sjkim dctx->generator = sctx->generator; 106280304Sjkim dctx->use_dsa = sctx->use_dsa; 107280304Sjkim return 1; 108280304Sjkim} 109238384Sjkim 110238384Sjkimstatic void pkey_dh_cleanup(EVP_PKEY_CTX *ctx) 111280304Sjkim{ 112280304Sjkim DH_PKEY_CTX *dctx = ctx->data; 113280304Sjkim if (dctx) 114280304Sjkim OPENSSL_free(dctx); 115280304Sjkim} 116238384Sjkim 117238384Sjkimstatic int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 118280304Sjkim{ 119280304Sjkim DH_PKEY_CTX *dctx = ctx->data; 120280304Sjkim switch (type) { 121280304Sjkim case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN: 122280304Sjkim if (p1 < 256) 123280304Sjkim return -2; 124280304Sjkim dctx->prime_len = p1; 125280304Sjkim return 1; 126238384Sjkim 127280304Sjkim case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR: 128280304Sjkim dctx->generator = p1; 129280304Sjkim return 1; 130238384Sjkim 131280304Sjkim case EVP_PKEY_CTRL_PEER_KEY: 132280304Sjkim /* Default behaviour is OK */ 133280304Sjkim return 1; 134238384Sjkim 135280304Sjkim default: 136280304Sjkim return -2; 137238384Sjkim 138280304Sjkim } 139280304Sjkim} 140238384Sjkim 141238384Sjkimstatic int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx, 142280304Sjkim const char *type, const char *value) 143280304Sjkim{ 144280304Sjkim if (!strcmp(type, "dh_paramgen_prime_len")) { 145280304Sjkim int len; 146280304Sjkim len = atoi(value); 147280304Sjkim return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len); 148280304Sjkim } 149280304Sjkim if (!strcmp(type, "dh_paramgen_generator")) { 150280304Sjkim int len; 151280304Sjkim len = atoi(value); 152280304Sjkim return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len); 153280304Sjkim } 154280304Sjkim return -2; 155280304Sjkim} 156238384Sjkim 157238384Sjkimstatic int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 158280304Sjkim{ 159280304Sjkim DH *dh = NULL; 160280304Sjkim DH_PKEY_CTX *dctx = ctx->data; 161280304Sjkim BN_GENCB *pcb, cb; 162280304Sjkim int ret; 163280304Sjkim if (ctx->pkey_gencb) { 164280304Sjkim pcb = &cb; 165280304Sjkim evp_pkey_set_cb_translate(pcb, ctx); 166280304Sjkim } else 167280304Sjkim pcb = NULL; 168280304Sjkim dh = DH_new(); 169280304Sjkim if (!dh) 170280304Sjkim return 0; 171280304Sjkim ret = DH_generate_parameters_ex(dh, 172280304Sjkim dctx->prime_len, dctx->generator, pcb); 173280304Sjkim if (ret) 174280304Sjkim EVP_PKEY_assign_DH(pkey, dh); 175280304Sjkim else 176280304Sjkim DH_free(dh); 177280304Sjkim return ret; 178280304Sjkim} 179238384Sjkim 180238384Sjkimstatic int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 181280304Sjkim{ 182280304Sjkim DH *dh = NULL; 183280304Sjkim if (ctx->pkey == NULL) { 184280304Sjkim DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET); 185280304Sjkim return 0; 186280304Sjkim } 187280304Sjkim dh = DH_new(); 188280304Sjkim if (!dh) 189280304Sjkim return 0; 190280304Sjkim EVP_PKEY_assign_DH(pkey, dh); 191280304Sjkim /* Note: if error return, pkey is freed by parent routine */ 192280304Sjkim if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) 193280304Sjkim return 0; 194280304Sjkim return DH_generate_key(pkey->pkey.dh); 195280304Sjkim} 196238384Sjkim 197280304Sjkimstatic int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, 198280304Sjkim size_t *keylen) 199280304Sjkim{ 200280304Sjkim int ret; 201280304Sjkim if (!ctx->pkey || !ctx->peerkey) { 202280304Sjkim DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET); 203280304Sjkim return 0; 204280304Sjkim } 205280304Sjkim ret = DH_compute_key(key, ctx->peerkey->pkey.dh->pub_key, 206280304Sjkim ctx->pkey->pkey.dh); 207280304Sjkim if (ret < 0) 208280304Sjkim return ret; 209280304Sjkim *keylen = ret; 210280304Sjkim return 1; 211280304Sjkim} 212238384Sjkim 213280304Sjkimconst EVP_PKEY_METHOD dh_pkey_meth = { 214280304Sjkim EVP_PKEY_DH, 215280304Sjkim EVP_PKEY_FLAG_AUTOARGLEN, 216280304Sjkim pkey_dh_init, 217280304Sjkim pkey_dh_copy, 218280304Sjkim pkey_dh_cleanup, 219238384Sjkim 220280304Sjkim 0, 221280304Sjkim pkey_dh_paramgen, 222238384Sjkim 223280304Sjkim 0, 224280304Sjkim pkey_dh_keygen, 225238384Sjkim 226280304Sjkim 0, 227280304Sjkim 0, 228238384Sjkim 229280304Sjkim 0, 230280304Sjkim 0, 231238384Sjkim 232280304Sjkim 0, 0, 233238384Sjkim 234280304Sjkim 0, 0, 0, 0, 235238384Sjkim 236280304Sjkim 0, 0, 237238384Sjkim 238280304Sjkim 0, 0, 239238384Sjkim 240280304Sjkim 0, 241280304Sjkim pkey_dh_derive, 242238384Sjkim 243280304Sjkim pkey_dh_ctrl, 244280304Sjkim pkey_dh_ctrl_str 245280304Sjkim}; 246