| 
									
										
										
										
											2006-04-13 07:51:24 +08:00
										 |  |  | /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
 | 
					
						
							|  |  |  |  * project 2006. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | /* ====================================================================
 | 
					
						
							|  |  |  |  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |  * modification, are permitted provided that the following conditions | 
					
						
							|  |  |  |  * are met: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 1. Redistributions of source code must retain the above copyright | 
					
						
							|  |  |  |  *    notice, this list of conditions and the following disclaimer.  | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 2. Redistributions in binary form must reproduce the above copyright | 
					
						
							|  |  |  |  *    notice, this list of conditions and the following disclaimer in | 
					
						
							|  |  |  |  *    the documentation and/or other materials provided with the | 
					
						
							|  |  |  |  *    distribution. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 3. All advertising materials mentioning features or use of this | 
					
						
							|  |  |  |  *    software must display the following acknowledgment: | 
					
						
							|  |  |  |  *    "This product includes software developed by the OpenSSL Project | 
					
						
							|  |  |  |  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | 
					
						
							|  |  |  |  *    endorse or promote products derived from this software without | 
					
						
							|  |  |  |  *    prior written permission. For written permission, please contact | 
					
						
							|  |  |  |  *    licensing@OpenSSL.org. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 5. Products derived from this software may not be called "OpenSSL" | 
					
						
							|  |  |  |  *    nor may "OpenSSL" appear in their names without prior written | 
					
						
							|  |  |  |  *    permission of the OpenSSL Project. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 6. Redistributions of any form whatsoever must retain the following | 
					
						
							|  |  |  |  *    acknowledgment: | 
					
						
							|  |  |  |  *    "This product includes software developed by the OpenSSL Project | 
					
						
							|  |  |  |  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | 
					
						
							|  |  |  |  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
					
						
							|  |  |  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 
					
						
							|  |  |  |  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR | 
					
						
							|  |  |  |  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
					
						
							|  |  |  |  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
					
						
							|  |  |  |  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 
					
						
							|  |  |  |  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
					
						
							|  |  |  |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | 
					
						
							|  |  |  |  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 
					
						
							|  |  |  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 
					
						
							|  |  |  |  * OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  * ==================================================================== | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This product includes cryptographic software written by Eric Young | 
					
						
							|  |  |  |  * (eay@cryptsoft.com).  This product includes software written by Tim | 
					
						
							|  |  |  |  * Hudson (tjh@cryptsoft.com). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include "cryptlib.h"
 | 
					
						
							|  |  |  | #include <openssl/asn1t.h>
 | 
					
						
							|  |  |  | #include <openssl/x509.h>
 | 
					
						
							|  |  |  | #include <openssl/rsa.h>
 | 
					
						
							|  |  |  | #include <openssl/evp.h>
 | 
					
						
							|  |  |  | #include "evp_locl.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* DH pkey context structure */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	/* Parameter gen parameters */ | 
					
						
							|  |  |  | 	int prime_len; | 
					
						
							|  |  |  | 	int generator; | 
					
						
							|  |  |  | 	int use_dsa; | 
					
						
							|  |  |  | 	/* Keygen callback info */ | 
					
						
							|  |  |  | 	int gentmp[2]; | 
					
						
							|  |  |  | 	/* message digest */ | 
					
						
							|  |  |  | 	} DH_PKEY_CTX; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int pkey_dh_init(EVP_PKEY_CTX *ctx) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	DH_PKEY_CTX *dctx; | 
					
						
							|  |  |  | 	dctx = OPENSSL_malloc(sizeof(DH_PKEY_CTX)); | 
					
						
							|  |  |  | 	if (!dctx) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	dctx->prime_len = 1024; | 
					
						
							|  |  |  | 	dctx->generator = 2; | 
					
						
							|  |  |  | 	dctx->use_dsa = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx->data = dctx; | 
					
						
							|  |  |  | 	ctx->keygen_info = dctx->gentmp; | 
					
						
							|  |  |  | 	ctx->keygen_info_count = 2; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	DH_PKEY_CTX *dctx = ctx->data; | 
					
						
							|  |  |  | 	if (dctx) | 
					
						
							|  |  |  | 		OPENSSL_free(dctx); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	DH_PKEY_CTX *dctx = ctx->data; | 
					
						
							|  |  |  | 	switch (type) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN: | 
					
						
							|  |  |  | 		if (p1 < 256) | 
					
						
							|  |  |  | 			return -2; | 
					
						
							|  |  |  | 		dctx->prime_len = p1; | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR: | 
					
						
							|  |  |  | 		dctx->generator = p1; | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-14 04:16:56 +08:00
										 |  |  | 		case EVP_PKEY_CTRL_PEER_KEY: | 
					
						
							|  |  |  | 		/* Default behaviour is OK */ | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-13 07:51:24 +08:00
										 |  |  | 		default: | 
					
						
							|  |  |  | 		return -2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-14 04:16:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-13 07:51:24 +08:00
										 |  |  | 			 | 
					
						
							|  |  |  | static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx, | 
					
						
							|  |  |  | 			const char *type, const char *value) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	if (!strcmp(type, "dh_paramgen_prime_len")) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		int len; | 
					
						
							|  |  |  | 		len = atoi(value); | 
					
						
							|  |  |  | 		return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	if (!strcmp(type, "dh_paramgen_generator")) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		int len; | 
					
						
							|  |  |  | 		len = atoi(value); | 
					
						
							|  |  |  | 		return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	return -2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	DH *dh = NULL; | 
					
						
							|  |  |  | 	DH_PKEY_CTX *dctx = ctx->data; | 
					
						
							|  |  |  | 	BN_GENCB *pcb, cb; | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 	if (ctx->pkey_gencb) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		pcb = &cb; | 
					
						
							|  |  |  | 		evp_pkey_set_cb_translate(pcb, ctx); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		pcb = NULL; | 
					
						
							|  |  |  | 	dh = DH_new(); | 
					
						
							|  |  |  | 	if (!dh) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	ret = DH_generate_parameters_ex(dh, | 
					
						
							|  |  |  | 					dctx->prime_len, dctx->generator, pcb); | 
					
						
							|  |  |  | 	if (ret) | 
					
						
							|  |  |  | 		EVP_PKEY_assign_DH(pkey, dh); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		DH_free(dh); | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	DH *dh = NULL; | 
					
						
							|  |  |  | 	if (ctx->pkey == NULL) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2006-04-13 08:26:05 +08:00
										 |  |  | 		DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET); | 
					
						
							| 
									
										
										
										
											2006-04-13 07:51:24 +08:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	dh = DH_new(); | 
					
						
							|  |  |  | 	if (!dh) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	EVP_PKEY_assign_DH(pkey, dh); | 
					
						
							|  |  |  | 	/* Note: if error return, pkey is freed by parent routine */ | 
					
						
							|  |  |  | 	if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	return DH_generate_key(pkey->pkey.dh); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-24 20:33:46 +08:00
										 |  |  | static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) | 
					
						
							| 
									
										
										
										
											2006-04-14 04:16:56 +08:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 	if (!ctx->pkey || !ctx->peerkey) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	ret = DH_compute_key(key, ctx->peerkey->pkey.dh->pub_key, | 
					
						
							|  |  |  | 							ctx->pkey->pkey.dh); | 
					
						
							|  |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 	*keylen = ret; | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-13 07:51:24 +08:00
										 |  |  | const EVP_PKEY_METHOD dh_pkey_meth =  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	EVP_PKEY_DH, | 
					
						
							| 
									
										
										
										
											2006-04-16 02:50:56 +08:00
										 |  |  | 	EVP_PKEY_FLAG_AUTOARGLEN, | 
					
						
							| 
									
										
										
										
											2006-04-13 07:51:24 +08:00
										 |  |  | 	pkey_dh_init, | 
					
						
							|  |  |  | 	pkey_dh_cleanup, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	pkey_dh_paramgen, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	pkey_dh_keygen, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	0,0, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	0,0,0,0, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	0,0, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	0,0, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-14 04:16:56 +08:00
										 |  |  | 	0, | 
					
						
							|  |  |  | 	pkey_dh_derive, | 
					
						
							| 
									
										
										
										
											2006-04-13 20:56:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-13 07:51:24 +08:00
										 |  |  | 	pkey_dh_ctrl, | 
					
						
							|  |  |  | 	pkey_dh_ctrl_str | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	}; |