dh_pmeth.c revision 296341
1/* 2 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 3 * 2006. 4 */ 5/* ==================================================================== 6 * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing@OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59#include <stdio.h> 60#include "cryptlib.h" 61#include <openssl/asn1t.h> 62#include <openssl/x509.h> 63#include <openssl/evp.h> 64#include <openssl/dh.h> 65#include <openssl/bn.h> 66#include "evp_locl.h" 67 68/* DH pkey context structure */ 69 70typedef struct { 71 /* Parameter gen parameters */ 72 int prime_len; 73 int generator; 74 int use_dsa; 75 /* Keygen callback info */ 76 int gentmp[2]; 77 /* message digest */ 78} DH_PKEY_CTX; 79 80static int pkey_dh_init(EVP_PKEY_CTX *ctx) 81{ 82 DH_PKEY_CTX *dctx; 83 dctx = OPENSSL_malloc(sizeof(DH_PKEY_CTX)); 84 if (!dctx) 85 return 0; 86 dctx->prime_len = 1024; 87 dctx->generator = 2; 88 dctx->use_dsa = 0; 89 90 ctx->data = dctx; 91 ctx->keygen_info = dctx->gentmp; 92 ctx->keygen_info_count = 2; 93 94 return 1; 95} 96 97static int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 98{ 99 DH_PKEY_CTX *dctx, *sctx; 100 if (!pkey_dh_init(dst)) 101 return 0; 102 sctx = src->data; 103 dctx = dst->data; 104 dctx->prime_len = sctx->prime_len; 105 dctx->generator = sctx->generator; 106 dctx->use_dsa = sctx->use_dsa; 107 return 1; 108} 109 110static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx) 111{ 112 DH_PKEY_CTX *dctx = ctx->data; 113 if (dctx) 114 OPENSSL_free(dctx); 115} 116 117static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 118{ 119 DH_PKEY_CTX *dctx = ctx->data; 120 switch (type) { 121 case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN: 122 if (p1 < 256) 123 return -2; 124 dctx->prime_len = p1; 125 return 1; 126 127 case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR: 128 dctx->generator = p1; 129 return 1; 130 131 case EVP_PKEY_CTRL_PEER_KEY: 132 /* Default behaviour is OK */ 133 return 1; 134 135 default: 136 return -2; 137 138 } 139} 140 141static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx, 142 const char *type, const char *value) 143{ 144 if (!strcmp(type, "dh_paramgen_prime_len")) { 145 int len; 146 len = atoi(value); 147 return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len); 148 } 149 if (!strcmp(type, "dh_paramgen_generator")) { 150 int len; 151 len = atoi(value); 152 return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len); 153 } 154 return -2; 155} 156 157static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 158{ 159 DH *dh = NULL; 160 DH_PKEY_CTX *dctx = ctx->data; 161 BN_GENCB *pcb, cb; 162 int ret; 163 if (ctx->pkey_gencb) { 164 pcb = &cb; 165 evp_pkey_set_cb_translate(pcb, ctx); 166 } else 167 pcb = NULL; 168 dh = DH_new(); 169 if (!dh) 170 return 0; 171 ret = DH_generate_parameters_ex(dh, 172 dctx->prime_len, dctx->generator, pcb); 173 if (ret) 174 EVP_PKEY_assign_DH(pkey, dh); 175 else 176 DH_free(dh); 177 return ret; 178} 179 180static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 181{ 182 DH *dh = NULL; 183 if (ctx->pkey == NULL) { 184 DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET); 185 return 0; 186 } 187 dh = DH_new(); 188 if (!dh) 189 return 0; 190 EVP_PKEY_assign_DH(pkey, dh); 191 /* Note: if error return, pkey is freed by parent routine */ 192 if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) 193 return 0; 194 return DH_generate_key(pkey->pkey.dh); 195} 196 197static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, 198 size_t *keylen) 199{ 200 int ret; 201 if (!ctx->pkey || !ctx->peerkey) { 202 DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET); 203 return 0; 204 } 205 ret = DH_compute_key(key, ctx->peerkey->pkey.dh->pub_key, 206 ctx->pkey->pkey.dh); 207 if (ret < 0) 208 return ret; 209 *keylen = ret; 210 return 1; 211} 212 213const EVP_PKEY_METHOD dh_pkey_meth = { 214 EVP_PKEY_DH, 215 EVP_PKEY_FLAG_AUTOARGLEN, 216 pkey_dh_init, 217 pkey_dh_copy, 218 pkey_dh_cleanup, 219 220 0, 221 pkey_dh_paramgen, 222 223 0, 224 pkey_dh_keygen, 225 226 0, 227 0, 228 229 0, 230 0, 231 232 0, 0, 233 234 0, 0, 0, 0, 235 236 0, 0, 237 238 0, 0, 239 240 0, 241 pkey_dh_derive, 242 243 pkey_dh_ctrl, 244 pkey_dh_ctrl_str 245}; 246