1 /* ==================================================================== 2 * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * 3. All advertising materials mentioning features or use of this 17 * software must display the following acknowledgment: 18 * "This product includes software developed by the OpenSSL Project 19 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 20 * 21 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 22 * endorse or promote products derived from this software without 23 * prior written permission. For written permission, please contact 24 * licensing (at) OpenSSL.org. 25 * 26 * 5. Products derived from this software may not be called "OpenSSL" 27 * nor may "OpenSSL" appear in their names without prior written 28 * permission of the OpenSSL Project. 29 * 30 * 6. Redistributions of any form whatsoever must retain the following 31 * acknowledgment: 32 * "This product includes software developed by the OpenSSL Project 33 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 34 * 35 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46 * OF THE POSSIBILITY OF SUCH DAMAGE. 47 * ==================================================================== 48 * 49 * This product includes cryptographic software written by Eric Young 50 * (eay (at) cryptsoft.com). This product includes software written by Tim 51 * Hudson (tjh (at) cryptsoft.com). */ 52 53 #include <openssl/evp.h> 54 55 #include <openssl/bio.h> 56 #include <openssl/bn.h> 57 #include <openssl/dsa.h> 58 #include <openssl/ec.h> 59 #include <openssl/ec_key.h> 60 #include <openssl/mem.h> 61 #include <openssl/rsa.h> 62 63 #include "../internal.h" 64 #include "../fipsmodule/rsa/internal.h" 65 66 67 static int bn_print(BIO *bp, const char *number, const BIGNUM *num, 68 uint8_t *buf, int off) { 69 if (num == NULL) { 70 return 1; 71 } 72 73 if (!BIO_indent(bp, off, 128)) { 74 return 0; 75 } 76 if (BN_is_zero(num)) { 77 if (BIO_printf(bp, "%s 0\n", number) <= 0) { 78 return 0; 79 } 80 return 1; 81 } 82 83 if (BN_num_bytes(num) <= sizeof(long)) { 84 const char *neg = BN_is_negative(num) ? "-" : ""; 85 if (BIO_printf(bp, "%s %s%lu (%s0x%lx)\n", number, neg, 86 (unsigned long)num->d[0], neg, 87 (unsigned long)num->d[0]) <= 0) { 88 return 0; 89 } 90 } else { 91 buf[0] = 0; 92 if (BIO_printf(bp, "%s%s", number, 93 (BN_is_negative(num)) ? " (Negative)" : "") <= 0) { 94 return 0; 95 } 96 int n = BN_bn2bin(num, &buf[1]); 97 98 if (buf[1] & 0x80) { 99 n++; 100 } else { 101 buf++; 102 } 103 104 int i; 105 for (i = 0; i < n; i++) { 106 if ((i % 15) == 0) { 107 if (BIO_puts(bp, "\n") <= 0 || 108 !BIO_indent(bp, off + 4, 128)) { 109 return 0; 110 } 111 } 112 if (BIO_printf(bp, "%02x%s", buf[i], ((i + 1) == n) ? "" : ":") <= 0) { 113 return 0; 114 } 115 } 116 if (BIO_write(bp, "\n", 1) <= 0) { 117 return 0; 118 } 119 } 120 return 1; 121 } 122 123 static void update_buflen(const BIGNUM *b, size_t *pbuflen) { 124 if (!b) { 125 return; 126 } 127 128 size_t len = BN_num_bytes(b); 129 if (*pbuflen < len) { 130 *pbuflen = len; 131 } 132 } 133 134 // RSA keys. 135 136 static int do_rsa_print(BIO *out, const RSA *rsa, int off, 137 int include_private) { 138 const char *s, *str; 139 uint8_t *m = NULL; 140 int ret = 0, mod_len = 0; 141 size_t buf_len = 0; 142 143 update_buflen(rsa->n, &buf_len); 144 update_buflen(rsa->e, &buf_len); 145 146 if (include_private) { 147 update_buflen(rsa->d, &buf_len); 148 update_buflen(rsa->p, &buf_len); 149 update_buflen(rsa->q, &buf_len); 150 update_buflen(rsa->dmp1, &buf_len); 151 update_buflen(rsa->dmq1, &buf_len); 152 update_buflen(rsa->iqmp, &buf_len); 153 } 154 155 m = (uint8_t *)OPENSSL_malloc(buf_len + 10); 156 if (m == NULL) { 157 OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE); 158 goto err; 159 } 160 161 if (rsa->n != NULL) { 162 mod_len = BN_num_bits(rsa->n); 163 } 164 165 if (!BIO_indent(out, off, 128)) { 166 goto err; 167 } 168 169 if (include_private && rsa->d) { 170 if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) { 171 goto err; 172 } 173 str = "modulus:"; 174 s = "publicExponent:"; 175 } else { 176 if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) { 177 goto err; 178 } 179 str = "Modulus:"; 180 s = "Exponent:"; 181 } 182 if (!bn_print(out, str, rsa->n, m, off) || 183 !bn_print(out, s, rsa->e, m, off)) { 184 goto err; 185 } 186 187 if (include_private) { 188 if (!bn_print(out, "privateExponent:", rsa->d, m, off) || 189 !bn_print(out, "prime1:", rsa->p, m, off) || 190 !bn_print(out, "prime2:", rsa->q, m, off) || 191 !bn_print(out, "exponent1:", rsa->dmp1, m, off) || 192 !bn_print(out, "exponent2:", rsa->dmq1, m, off) || 193 !bn_print(out, "coefficient:", rsa->iqmp, m, off)) { 194 goto err; 195 } 196 } 197 ret = 1; 198 199 err: 200 OPENSSL_free(m); 201 return ret; 202 } 203 204 static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, 205 ASN1_PCTX *ctx) { 206 return do_rsa_print(bp, pkey->pkey.rsa, indent, 0); 207 } 208 209 static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, 210 ASN1_PCTX *ctx) { 211 return do_rsa_print(bp, pkey->pkey.rsa, indent, 1); 212 } 213 214 215 // DSA keys. 216 217 static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) { 218 uint8_t *m = NULL; 219 int ret = 0; 220 size_t buf_len = 0; 221 const char *ktype = NULL; 222 223 const BIGNUM *priv_key, *pub_key; 224 225 priv_key = NULL; 226 if (ptype == 2) { 227 priv_key = x->priv_key; 228 } 229 230 pub_key = NULL; 231 if (ptype > 0) { 232 pub_key = x->pub_key; 233 } 234 235 ktype = "DSA-Parameters"; 236 if (ptype == 2) { 237 ktype = "Private-Key"; 238 } else if (ptype == 1) { 239 ktype = "Public-Key"; 240 } 241 242 update_buflen(x->p, &buf_len); 243 update_buflen(x->q, &buf_len); 244 update_buflen(x->g, &buf_len); 245 update_buflen(priv_key, &buf_len); 246 update_buflen(pub_key, &buf_len); 247 248 m = (uint8_t *)OPENSSL_malloc(buf_len + 10); 249 if (m == NULL) { 250 OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE); 251 goto err; 252 } 253 254 if (priv_key) { 255 if (!BIO_indent(bp, off, 128) || 256 BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) { 257 goto err; 258 } 259 } 260 261 if (!bn_print(bp, "priv:", priv_key, m, off) || 262 !bn_print(bp, "pub: ", pub_key, m, off) || 263 !bn_print(bp, "P: ", x->p, m, off) || 264 !bn_print(bp, "Q: ", x->q, m, off) || 265 !bn_print(bp, "G: ", x->g, m, off)) { 266 goto err; 267 } 268 ret = 1; 269 270 err: 271 OPENSSL_free(m); 272 return ret; 273 } 274 275 static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, 276 ASN1_PCTX *ctx) { 277 return do_dsa_print(bp, pkey->pkey.dsa, indent, 0); 278 } 279 280 static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, 281 ASN1_PCTX *ctx) { 282 return do_dsa_print(bp, pkey->pkey.dsa, indent, 1); 283 } 284 285 static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, 286 ASN1_PCTX *ctx) { 287 return do_dsa_print(bp, pkey->pkey.dsa, indent, 2); 288 } 289 290 291 // EC keys. 292 293 static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) { 294 uint8_t *buffer = NULL; 295 const char *ecstr; 296 size_t buf_len = 0, i; 297 int ret = 0, reason = ERR_R_BIO_LIB; 298 BIGNUM *order = NULL; 299 BN_CTX *ctx = NULL; 300 const EC_GROUP *group; 301 const EC_POINT *public_key; 302 const BIGNUM *priv_key; 303 uint8_t *pub_key_bytes = NULL; 304 size_t pub_key_bytes_len = 0; 305 306 if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { 307 reason = ERR_R_PASSED_NULL_PARAMETER; 308 goto err; 309 } 310 311 ctx = BN_CTX_new(); 312 if (ctx == NULL) { 313 reason = ERR_R_MALLOC_FAILURE; 314 goto err; 315 } 316 317 if (ktype > 0) { 318 public_key = EC_KEY_get0_public_key(x); 319 if (public_key != NULL) { 320 pub_key_bytes_len = EC_POINT_point2oct( 321 group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx); 322 if (pub_key_bytes_len == 0) { 323 reason = ERR_R_MALLOC_FAILURE; 324 goto err; 325 } 326 pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len); 327 if (pub_key_bytes == NULL) { 328 reason = ERR_R_MALLOC_FAILURE; 329 goto err; 330 } 331 pub_key_bytes_len = 332 EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x), 333 pub_key_bytes, pub_key_bytes_len, ctx); 334 if (pub_key_bytes_len == 0) { 335 reason = ERR_R_MALLOC_FAILURE; 336 goto err; 337 } 338 buf_len = pub_key_bytes_len; 339 } 340 } 341 342 if (ktype == 2) { 343 priv_key = EC_KEY_get0_private_key(x); 344 if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) { 345 buf_len = i; 346 } 347 } else { 348 priv_key = NULL; 349 } 350 351 if (ktype > 0) { 352 buf_len += 10; 353 if ((buffer = OPENSSL_malloc(buf_len)) == NULL) { 354 reason = ERR_R_MALLOC_FAILURE; 355 goto err; 356 } 357 } 358 if (ktype == 2) { 359 ecstr = "Private-Key"; 360 } else if (ktype == 1) { 361 ecstr = "Public-Key"; 362 } else { 363 ecstr = "ECDSA-Parameters"; 364 } 365 366 if (!BIO_indent(bp, off, 128)) { 367 goto err; 368 } 369 order = BN_new(); 370 if (order == NULL || !EC_GROUP_get_order(group, order, NULL) || 371 BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) { 372 goto err; 373 } 374 375 if ((priv_key != NULL) && 376 !bn_print(bp, "priv:", priv_key, buffer, off)) { 377 goto err; 378 } 379 if (pub_key_bytes != NULL) { 380 BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off); 381 } 382 // TODO(fork): implement 383 /* 384 if (!ECPKParameters_print(bp, group, off)) 385 goto err; */ 386 ret = 1; 387 388 err: 389 if (!ret) { 390 OPENSSL_PUT_ERROR(EVP, reason); 391 } 392 OPENSSL_free(pub_key_bytes); 393 BN_free(order); 394 BN_CTX_free(ctx); 395 OPENSSL_free(buffer); 396 return ret; 397 } 398 399 static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, 400 ASN1_PCTX *ctx) { 401 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0); 402 } 403 404 static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, 405 ASN1_PCTX *ctx) { 406 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1); 407 } 408 409 410 static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, 411 ASN1_PCTX *ctx) { 412 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2); 413 } 414 415 416 typedef struct { 417 int type; 418 int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx); 419 int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent, 420 ASN1_PCTX *pctx); 421 int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent, 422 ASN1_PCTX *pctx); 423 } EVP_PKEY_PRINT_METHOD; 424 425 static EVP_PKEY_PRINT_METHOD kPrintMethods[] = { 426 { 427 EVP_PKEY_RSA, 428 rsa_pub_print, 429 rsa_priv_print, 430 NULL /* param_print */, 431 }, 432 { 433 EVP_PKEY_DSA, 434 dsa_pub_print, 435 dsa_priv_print, 436 dsa_param_print, 437 }, 438 { 439 EVP_PKEY_EC, 440 eckey_pub_print, 441 eckey_priv_print, 442 eckey_param_print, 443 }, 444 }; 445 446 static size_t kPrintMethodsLen = OPENSSL_ARRAY_SIZE(kPrintMethods); 447 448 static EVP_PKEY_PRINT_METHOD *find_method(int type) { 449 for (size_t i = 0; i < kPrintMethodsLen; i++) { 450 if (kPrintMethods[i].type == type) { 451 return &kPrintMethods[i]; 452 } 453 } 454 return NULL; 455 } 456 457 static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent, 458 const char *kstr) { 459 BIO_indent(out, indent, 128); 460 BIO_printf(out, "%s algorithm unsupported\n", kstr); 461 return 1; 462 } 463 464 int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent, 465 ASN1_PCTX *pctx) { 466 EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type); 467 if (method != NULL && method->pub_print != NULL) { 468 return method->pub_print(out, pkey, indent, pctx); 469 } 470 return print_unsupported(out, pkey, indent, "Public Key"); 471 } 472 473 int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent, 474 ASN1_PCTX *pctx) { 475 EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type); 476 if (method != NULL && method->priv_print != NULL) { 477 return method->priv_print(out, pkey, indent, pctx); 478 } 479 return print_unsupported(out, pkey, indent, "Private Key"); 480 } 481 482 int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent, 483 ASN1_PCTX *pctx) { 484 EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type); 485 if (method != NULL && method->param_print != NULL) { 486 return method->param_print(out, pkey, indent, pctx); 487 } 488 return print_unsupported(out, pkey, indent, "Parameters"); 489 } 490