dh_ameth.c revision 296373
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/x509.h> 62#include <openssl/asn1.h> 63#include <openssl/dh.h> 64#include <openssl/bn.h> 65#include "asn1_locl.h" 66 67static void int_dh_free(EVP_PKEY *pkey) 68{ 69 DH_free(pkey->pkey.dh); 70} 71 72static int dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) 73{ 74 const unsigned char *p, *pm; 75 int pklen, pmlen; 76 int ptype; 77 void *pval; 78 ASN1_STRING *pstr; 79 X509_ALGOR *palg; 80 ASN1_INTEGER *public_key = NULL; 81 82 DH *dh = NULL; 83 84 if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) 85 return 0; 86 X509_ALGOR_get0(NULL, &ptype, &pval, palg); 87 88 if (ptype != V_ASN1_SEQUENCE) { 89 DHerr(DH_F_DH_PUB_DECODE, DH_R_PARAMETER_ENCODING_ERROR); 90 goto err; 91 } 92 93 pstr = pval; 94 pm = pstr->data; 95 pmlen = pstr->length; 96 97 if (!(dh = d2i_DHparams(NULL, &pm, pmlen))) { 98 DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR); 99 goto err; 100 } 101 102 if (!(public_key = d2i_ASN1_INTEGER(NULL, &p, pklen))) { 103 DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR); 104 goto err; 105 } 106 107 /* We have parameters now set public key */ 108 if (!(dh->pub_key = ASN1_INTEGER_to_BN(public_key, NULL))) { 109 DHerr(DH_F_DH_PUB_DECODE, DH_R_BN_DECODE_ERROR); 110 goto err; 111 } 112 113 ASN1_INTEGER_free(public_key); 114 EVP_PKEY_assign_DH(pkey, dh); 115 return 1; 116 117 err: 118 if (public_key) 119 ASN1_INTEGER_free(public_key); 120 if (dh) 121 DH_free(dh); 122 return 0; 123 124} 125 126static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) 127{ 128 DH *dh; 129 int ptype; 130 unsigned char *penc = NULL; 131 int penclen; 132 ASN1_STRING *str; 133 ASN1_INTEGER *pub_key = NULL; 134 135 dh = pkey->pkey.dh; 136 137 str = ASN1_STRING_new(); 138 if (!str) { 139 DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE); 140 goto err; 141 } 142 str->length = i2d_DHparams(dh, &str->data); 143 if (str->length <= 0) { 144 DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE); 145 goto err; 146 } 147 ptype = V_ASN1_SEQUENCE; 148 149 pub_key = BN_to_ASN1_INTEGER(dh->pub_key, NULL); 150 if (!pub_key) 151 goto err; 152 153 penclen = i2d_ASN1_INTEGER(pub_key, &penc); 154 155 ASN1_INTEGER_free(pub_key); 156 157 if (penclen <= 0) { 158 DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE); 159 goto err; 160 } 161 162 if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_DH), 163 ptype, str, penc, penclen)) 164 return 1; 165 166 err: 167 if (penc) 168 OPENSSL_free(penc); 169 if (str) 170 ASN1_STRING_free(str); 171 172 return 0; 173} 174 175/* 176 * PKCS#8 DH is defined in PKCS#11 of all places. It is similar to DH in that 177 * the AlgorithmIdentifier contains the paramaters, the private key is 178 * explcitly included and the pubkey must be recalculated. 179 */ 180 181static int dh_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) 182{ 183 const unsigned char *p, *pm; 184 int pklen, pmlen; 185 int ptype; 186 void *pval; 187 ASN1_STRING *pstr; 188 X509_ALGOR *palg; 189 ASN1_INTEGER *privkey = NULL; 190 191 DH *dh = NULL; 192 193 if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) 194 return 0; 195 196 X509_ALGOR_get0(NULL, &ptype, &pval, palg); 197 198 if (ptype != V_ASN1_SEQUENCE) 199 goto decerr; 200 201 if (!(privkey = d2i_ASN1_INTEGER(NULL, &p, pklen))) 202 goto decerr; 203 204 pstr = pval; 205 pm = pstr->data; 206 pmlen = pstr->length; 207 if (!(dh = d2i_DHparams(NULL, &pm, pmlen))) 208 goto decerr; 209 /* We have parameters now set private key */ 210 if (!(dh->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) { 211 DHerr(DH_F_DH_PRIV_DECODE, DH_R_BN_ERROR); 212 goto dherr; 213 } 214 /* Calculate public key */ 215 if (!DH_generate_key(dh)) 216 goto dherr; 217 218 EVP_PKEY_assign_DH(pkey, dh); 219 220 ASN1_STRING_clear_free(privkey); 221 222 return 1; 223 224 decerr: 225 DHerr(DH_F_DH_PRIV_DECODE, EVP_R_DECODE_ERROR); 226 dherr: 227 DH_free(dh); 228 ASN1_STRING_clear_free(privkey); 229 return 0; 230} 231 232static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) 233{ 234 ASN1_STRING *params = NULL; 235 ASN1_INTEGER *prkey = NULL; 236 unsigned char *dp = NULL; 237 int dplen; 238 239 params = ASN1_STRING_new(); 240 241 if (!params) { 242 DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); 243 goto err; 244 } 245 246 params->length = i2d_DHparams(pkey->pkey.dh, ¶ms->data); 247 if (params->length <= 0) { 248 DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); 249 goto err; 250 } 251 params->type = V_ASN1_SEQUENCE; 252 253 /* Get private key into integer */ 254 prkey = BN_to_ASN1_INTEGER(pkey->pkey.dh->priv_key, NULL); 255 256 if (!prkey) { 257 DHerr(DH_F_DH_PRIV_ENCODE, DH_R_BN_ERROR); 258 goto err; 259 } 260 261 dplen = i2d_ASN1_INTEGER(prkey, &dp); 262 263 ASN1_STRING_clear_free(prkey); 264 prkey = NULL; 265 266 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_dhKeyAgreement), 0, 267 V_ASN1_SEQUENCE, params, dp, dplen)) 268 goto err; 269 270 return 1; 271 272 err: 273 if (dp != NULL) 274 OPENSSL_free(dp); 275 if (params != NULL) 276 ASN1_STRING_free(params); 277 if (prkey != NULL) 278 ASN1_STRING_clear_free(prkey); 279 return 0; 280} 281 282static void update_buflen(const BIGNUM *b, size_t *pbuflen) 283{ 284 size_t i; 285 if (!b) 286 return; 287 if (*pbuflen < (i = (size_t)BN_num_bytes(b))) 288 *pbuflen = i; 289} 290 291static int dh_param_decode(EVP_PKEY *pkey, 292 const unsigned char **pder, int derlen) 293{ 294 DH *dh; 295 if (!(dh = d2i_DHparams(NULL, pder, derlen))) { 296 DHerr(DH_F_DH_PARAM_DECODE, ERR_R_DH_LIB); 297 return 0; 298 } 299 EVP_PKEY_assign_DH(pkey, dh); 300 return 1; 301} 302 303static int dh_param_encode(const EVP_PKEY *pkey, unsigned char **pder) 304{ 305 return i2d_DHparams(pkey->pkey.dh, pder); 306} 307 308static int do_dh_print(BIO *bp, const DH *x, int indent, 309 ASN1_PCTX *ctx, int ptype) 310{ 311 unsigned char *m = NULL; 312 int reason = ERR_R_BUF_LIB, ret = 0; 313 size_t buf_len = 0; 314 315 const char *ktype = NULL; 316 317 BIGNUM *priv_key, *pub_key; 318 319 if (ptype == 2) 320 priv_key = x->priv_key; 321 else 322 priv_key = NULL; 323 324 if (ptype > 0) 325 pub_key = x->pub_key; 326 else 327 pub_key = NULL; 328 329 update_buflen(x->p, &buf_len); 330 331 if (buf_len == 0) { 332 reason = ERR_R_PASSED_NULL_PARAMETER; 333 goto err; 334 } 335 336 update_buflen(x->g, &buf_len); 337 update_buflen(pub_key, &buf_len); 338 update_buflen(priv_key, &buf_len); 339 340 if (ptype == 2) 341 ktype = "PKCS#3 DH Private-Key"; 342 else if (ptype == 1) 343 ktype = "PKCS#3 DH Public-Key"; 344 else 345 ktype = "PKCS#3 DH Parameters"; 346 347 m = OPENSSL_malloc(buf_len + 10); 348 if (m == NULL) { 349 reason = ERR_R_MALLOC_FAILURE; 350 goto err; 351 } 352 353 BIO_indent(bp, indent, 128); 354 if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) 355 goto err; 356 indent += 4; 357 358 if (!ASN1_bn_print(bp, "private-key:", priv_key, m, indent)) 359 goto err; 360 if (!ASN1_bn_print(bp, "public-key:", pub_key, m, indent)) 361 goto err; 362 363 if (!ASN1_bn_print(bp, "prime:", x->p, m, indent)) 364 goto err; 365 if (!ASN1_bn_print(bp, "generator:", x->g, m, indent)) 366 goto err; 367 if (x->length != 0) { 368 BIO_indent(bp, indent, 128); 369 if (BIO_printf(bp, "recommended-private-length: %d bits\n", 370 (int)x->length) <= 0) 371 goto err; 372 } 373 374 ret = 1; 375 if (0) { 376 err: 377 DHerr(DH_F_DO_DH_PRINT, reason); 378 } 379 if (m != NULL) 380 OPENSSL_free(m); 381 return (ret); 382} 383 384static int int_dh_size(const EVP_PKEY *pkey) 385{ 386 return (DH_size(pkey->pkey.dh)); 387} 388 389static int dh_bits(const EVP_PKEY *pkey) 390{ 391 return BN_num_bits(pkey->pkey.dh->p); 392} 393 394static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) 395{ 396 if (BN_cmp(a->pkey.dh->p, b->pkey.dh->p) || 397 BN_cmp(a->pkey.dh->g, b->pkey.dh->g)) 398 return 0; 399 else 400 return 1; 401} 402 403static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) 404{ 405 BIGNUM *a; 406 407 if ((a = BN_dup(from->pkey.dh->p)) == NULL) 408 return 0; 409 if (to->pkey.dh->p != NULL) 410 BN_free(to->pkey.dh->p); 411 to->pkey.dh->p = a; 412 413 if ((a = BN_dup(from->pkey.dh->g)) == NULL) 414 return 0; 415 if (to->pkey.dh->g != NULL) 416 BN_free(to->pkey.dh->g); 417 to->pkey.dh->g = a; 418 419 return 1; 420} 421 422static int dh_missing_parameters(const EVP_PKEY *a) 423{ 424 if (!a->pkey.dh->p || !a->pkey.dh->g) 425 return 1; 426 return 0; 427} 428 429static int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) 430{ 431 if (dh_cmp_parameters(a, b) == 0) 432 return 0; 433 if (BN_cmp(b->pkey.dh->pub_key, a->pkey.dh->pub_key) != 0) 434 return 0; 435 else 436 return 1; 437} 438 439static int dh_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, 440 ASN1_PCTX *ctx) 441{ 442 return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 0); 443} 444 445static int dh_public_print(BIO *bp, const EVP_PKEY *pkey, int indent, 446 ASN1_PCTX *ctx) 447{ 448 return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 1); 449} 450 451static int dh_private_print(BIO *bp, const EVP_PKEY *pkey, int indent, 452 ASN1_PCTX *ctx) 453{ 454 return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 2); 455} 456 457int DHparams_print(BIO *bp, const DH *x) 458{ 459 return do_dh_print(bp, x, 4, NULL, 0); 460} 461 462const EVP_PKEY_ASN1_METHOD dh_asn1_meth = { 463 EVP_PKEY_DH, 464 EVP_PKEY_DH, 465 0, 466 467 "DH", 468 "OpenSSL PKCS#3 DH method", 469 470 dh_pub_decode, 471 dh_pub_encode, 472 dh_pub_cmp, 473 dh_public_print, 474 475 dh_priv_decode, 476 dh_priv_encode, 477 dh_private_print, 478 479 int_dh_size, 480 dh_bits, 481 482 dh_param_decode, 483 dh_param_encode, 484 dh_missing_parameters, 485 dh_copy_parameters, 486 dh_cmp_parameters, 487 dh_param_print, 488 0, 489 490 int_dh_free, 491 0 492}; 493