dh_ameth.c 12 KB

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