1238384Sjkim/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2238384Sjkim * project 2006. 3238384Sjkim */ 4238384Sjkim/* ==================================================================== 5238384Sjkim * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 6238384Sjkim * 7238384Sjkim * Redistribution and use in source and binary forms, with or without 8238384Sjkim * modification, are permitted provided that the following conditions 9238384Sjkim * are met: 10238384Sjkim * 11238384Sjkim * 1. Redistributions of source code must retain the above copyright 12238384Sjkim * notice, this list of conditions and the following disclaimer. 13238384Sjkim * 14238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 15238384Sjkim * notice, this list of conditions and the following disclaimer in 16238384Sjkim * the documentation and/or other materials provided with the 17238384Sjkim * distribution. 18238384Sjkim * 19238384Sjkim * 3. All advertising materials mentioning features or use of this 20238384Sjkim * software must display the following acknowledgment: 21238384Sjkim * "This product includes software developed by the OpenSSL Project 22238384Sjkim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 23238384Sjkim * 24238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 25238384Sjkim * endorse or promote products derived from this software without 26238384Sjkim * prior written permission. For written permission, please contact 27238384Sjkim * licensing@OpenSSL.org. 28238384Sjkim * 29238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 30238384Sjkim * nor may "OpenSSL" appear in their names without prior written 31238384Sjkim * permission of the OpenSSL Project. 32238384Sjkim * 33238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 34238384Sjkim * acknowledgment: 35238384Sjkim * "This product includes software developed by the OpenSSL Project 36238384Sjkim * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 37238384Sjkim * 38238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 39238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 41238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 42238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 47238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 48238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 49238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 50238384Sjkim * ==================================================================== 51238384Sjkim * 52238384Sjkim * This product includes cryptographic software written by Eric Young 53238384Sjkim * (eay@cryptsoft.com). This product includes software written by Tim 54238384Sjkim * Hudson (tjh@cryptsoft.com). 55238384Sjkim * 56238384Sjkim */ 57238384Sjkim 58238384Sjkim#include <stdio.h> 59238384Sjkim#include "cryptlib.h" 60238384Sjkim#include <openssl/asn1t.h> 61238384Sjkim#include <openssl/x509.h> 62238384Sjkim#include <openssl/evp.h> 63238384Sjkim#include <openssl/dh.h> 64238384Sjkim#include <openssl/bn.h> 65238384Sjkim#include "evp_locl.h" 66238384Sjkim 67238384Sjkim/* DH pkey context structure */ 68238384Sjkim 69238384Sjkimtypedef struct 70238384Sjkim { 71238384Sjkim /* Parameter gen parameters */ 72238384Sjkim int prime_len; 73238384Sjkim int generator; 74238384Sjkim int use_dsa; 75238384Sjkim /* Keygen callback info */ 76238384Sjkim int gentmp[2]; 77238384Sjkim /* message digest */ 78238384Sjkim } DH_PKEY_CTX; 79238384Sjkim 80238384Sjkimstatic int pkey_dh_init(EVP_PKEY_CTX *ctx) 81238384Sjkim { 82238384Sjkim DH_PKEY_CTX *dctx; 83238384Sjkim dctx = OPENSSL_malloc(sizeof(DH_PKEY_CTX)); 84238384Sjkim if (!dctx) 85238384Sjkim return 0; 86238384Sjkim dctx->prime_len = 1024; 87238384Sjkim dctx->generator = 2; 88238384Sjkim dctx->use_dsa = 0; 89238384Sjkim 90238384Sjkim ctx->data = dctx; 91238384Sjkim ctx->keygen_info = dctx->gentmp; 92238384Sjkim ctx->keygen_info_count = 2; 93238384Sjkim 94238384Sjkim return 1; 95238384Sjkim } 96238384Sjkim 97238384Sjkimstatic int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 98238384Sjkim { 99238384Sjkim DH_PKEY_CTX *dctx, *sctx; 100238384Sjkim if (!pkey_dh_init(dst)) 101238384Sjkim return 0; 102238384Sjkim sctx = src->data; 103238384Sjkim dctx = dst->data; 104238384Sjkim dctx->prime_len = sctx->prime_len; 105238384Sjkim dctx->generator = sctx->generator; 106238384Sjkim dctx->use_dsa = sctx->use_dsa; 107238384Sjkim return 1; 108238384Sjkim } 109238384Sjkim 110238384Sjkimstatic void pkey_dh_cleanup(EVP_PKEY_CTX *ctx) 111238384Sjkim { 112238384Sjkim DH_PKEY_CTX *dctx = ctx->data; 113238384Sjkim if (dctx) 114238384Sjkim OPENSSL_free(dctx); 115238384Sjkim } 116238384Sjkim 117238384Sjkimstatic int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 118238384Sjkim { 119238384Sjkim DH_PKEY_CTX *dctx = ctx->data; 120238384Sjkim switch (type) 121238384Sjkim { 122238384Sjkim case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN: 123238384Sjkim if (p1 < 256) 124238384Sjkim return -2; 125238384Sjkim dctx->prime_len = p1; 126238384Sjkim return 1; 127238384Sjkim 128238384Sjkim case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR: 129238384Sjkim dctx->generator = p1; 130238384Sjkim return 1; 131238384Sjkim 132238384Sjkim case EVP_PKEY_CTRL_PEER_KEY: 133238384Sjkim /* Default behaviour is OK */ 134238384Sjkim return 1; 135238384Sjkim 136238384Sjkim default: 137238384Sjkim return -2; 138238384Sjkim 139238384Sjkim } 140238384Sjkim } 141238384Sjkim 142238384Sjkim 143238384Sjkimstatic int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx, 144238384Sjkim const char *type, const char *value) 145238384Sjkim { 146238384Sjkim if (!strcmp(type, "dh_paramgen_prime_len")) 147238384Sjkim { 148238384Sjkim int len; 149238384Sjkim len = atoi(value); 150238384Sjkim return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len); 151238384Sjkim } 152238384Sjkim if (!strcmp(type, "dh_paramgen_generator")) 153238384Sjkim { 154238384Sjkim int len; 155238384Sjkim len = atoi(value); 156238384Sjkim return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len); 157238384Sjkim } 158238384Sjkim return -2; 159238384Sjkim } 160238384Sjkim 161238384Sjkimstatic int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 162238384Sjkim { 163238384Sjkim DH *dh = NULL; 164238384Sjkim DH_PKEY_CTX *dctx = ctx->data; 165238384Sjkim BN_GENCB *pcb, cb; 166238384Sjkim int ret; 167238384Sjkim if (ctx->pkey_gencb) 168238384Sjkim { 169238384Sjkim pcb = &cb; 170238384Sjkim evp_pkey_set_cb_translate(pcb, ctx); 171238384Sjkim } 172238384Sjkim else 173238384Sjkim pcb = NULL; 174238384Sjkim dh = DH_new(); 175238384Sjkim if (!dh) 176238384Sjkim return 0; 177238384Sjkim ret = DH_generate_parameters_ex(dh, 178238384Sjkim dctx->prime_len, dctx->generator, pcb); 179238384Sjkim if (ret) 180238384Sjkim EVP_PKEY_assign_DH(pkey, dh); 181238384Sjkim else 182238384Sjkim DH_free(dh); 183238384Sjkim return ret; 184238384Sjkim } 185238384Sjkim 186238384Sjkimstatic int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 187238384Sjkim { 188238384Sjkim DH *dh = NULL; 189238384Sjkim if (ctx->pkey == NULL) 190238384Sjkim { 191238384Sjkim DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET); 192238384Sjkim return 0; 193238384Sjkim } 194238384Sjkim dh = DH_new(); 195238384Sjkim if (!dh) 196238384Sjkim return 0; 197238384Sjkim EVP_PKEY_assign_DH(pkey, dh); 198238384Sjkim /* Note: if error return, pkey is freed by parent routine */ 199238384Sjkim if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) 200238384Sjkim return 0; 201238384Sjkim return DH_generate_key(pkey->pkey.dh); 202238384Sjkim } 203238384Sjkim 204238384Sjkimstatic int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) 205238384Sjkim { 206238384Sjkim int ret; 207238384Sjkim if (!ctx->pkey || !ctx->peerkey) 208238384Sjkim { 209238384Sjkim DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET); 210238384Sjkim return 0; 211238384Sjkim } 212238384Sjkim ret = DH_compute_key(key, ctx->peerkey->pkey.dh->pub_key, 213238384Sjkim ctx->pkey->pkey.dh); 214238384Sjkim if (ret < 0) 215238384Sjkim return ret; 216238384Sjkim *keylen = ret; 217238384Sjkim return 1; 218238384Sjkim } 219238384Sjkim 220238384Sjkimconst EVP_PKEY_METHOD dh_pkey_meth = 221238384Sjkim { 222238384Sjkim EVP_PKEY_DH, 223238384Sjkim EVP_PKEY_FLAG_AUTOARGLEN, 224238384Sjkim pkey_dh_init, 225238384Sjkim pkey_dh_copy, 226238384Sjkim pkey_dh_cleanup, 227238384Sjkim 228238384Sjkim 0, 229238384Sjkim pkey_dh_paramgen, 230238384Sjkim 231238384Sjkim 0, 232238384Sjkim pkey_dh_keygen, 233238384Sjkim 234238384Sjkim 0, 235238384Sjkim 0, 236238384Sjkim 237238384Sjkim 0, 238238384Sjkim 0, 239238384Sjkim 240238384Sjkim 0,0, 241238384Sjkim 242238384Sjkim 0,0,0,0, 243238384Sjkim 244238384Sjkim 0,0, 245238384Sjkim 246238384Sjkim 0,0, 247238384Sjkim 248238384Sjkim 0, 249238384Sjkim pkey_dh_derive, 250238384Sjkim 251238384Sjkim pkey_dh_ctrl, 252238384Sjkim pkey_dh_ctrl_str 253238384Sjkim 254238384Sjkim }; 255