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