root/source4/heimdal/lib/hcrypto/rsa.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. RSA_new
  2. RSA_new_method
  3. RSA_free
  4. RSA_up_ref
  5. RSA_get_method
  6. RSA_set_method
  7. RSA_set_app_data
  8. RSA_get_app_data
  9. RSA_check_key
  10. RSA_size
  11. RSAFUNC
  12. RSA_verify
  13. RSAFUNC
  14. null_rsa_init
  15. null_rsa_finish
  16. RSA_null_method
  17. RSA_get_default_method
  18. RSA_set_default_method
  19. heim_int2BN
  20. bn2heim_int
  21. d2i_RSAPrivateKey
  22. i2d_RSAPrivateKey
  23. i2d_RSAPublicKey

   1 /*
   2  * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan
   3  * (Royal Institute of Technology, Stockholm, Sweden).
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  *
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  *
  17  * 3. Neither the name of the Institute nor the names of its contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 
  34 #ifdef HAVE_CONFIG_H
  35 #include <config.h>
  36 #endif
  37 
  38 RCSID("$Id$");
  39 
  40 #include <stdio.h>
  41 #include <stdlib.h>
  42 #include <krb5-types.h>
  43 #include <rfc2459_asn1.h>
  44 
  45 #include <rsa.h>
  46 
  47 #include <roken.h>
  48 
  49 /**
  50  * @page page_rsa RSA - public-key cryptography
  51  *
  52  * RSA is named by its inventors (Ron Rivest, Adi Shamir, and Leonard
  53  * Adleman) (published in 1977), patented expired in 21 September 2000.
  54  *
  55  * See the library functions here: @ref hcrypto_rsa
  56  */
  57 
  58 /**
  59  * Same as RSA_new_method() using NULL as engine.
  60  *
  61  * @return a newly allocated RSA object. Free with RSA_free().
  62  *
  63  * @ingroup hcrypto_rsa
  64  */
  65 
  66 RSA *
  67 RSA_new(void)
     /* [<][>][^][v][top][bottom][index][help] */
  68 {
  69     return RSA_new_method(NULL);
  70 }
  71 
  72 /**
  73  * Allocate a new RSA object using the engine, if NULL is specified as
  74  * the engine, use the default RSA engine as returned by
  75  * ENGINE_get_default_RSA().
  76  *
  77  * @param engine Specific what ENGINE RSA provider should be used.
  78  *
  79  * @return a newly allocated RSA object. Free with RSA_free().
  80  *
  81  * @ingroup hcrypto_rsa
  82  */
  83 
  84 RSA *
  85 RSA_new_method(ENGINE *engine)
     /* [<][>][^][v][top][bottom][index][help] */
  86 {
  87     RSA *rsa;
  88 
  89     rsa = calloc(1, sizeof(*rsa));
  90     if (rsa == NULL)
  91         return NULL;
  92 
  93     rsa->references = 1;
  94 
  95     if (engine) {
  96         ENGINE_up_ref(engine);
  97         rsa->engine = engine;
  98     } else {
  99         rsa->engine = ENGINE_get_default_RSA();
 100     }
 101 
 102     if (rsa->engine) {
 103         rsa->meth = ENGINE_get_RSA(rsa->engine);
 104         if (rsa->meth == NULL) {
 105             ENGINE_finish(engine);
 106             free(rsa);
 107             return 0;
 108         }
 109     }
 110 
 111     if (rsa->meth == NULL)
 112         rsa->meth = rk_UNCONST(RSA_get_default_method());
 113 
 114     (*rsa->meth->init)(rsa);
 115 
 116     return rsa;
 117 }
 118 
 119 /**
 120  * Free an allocation RSA object.
 121  *
 122  * @param rsa the RSA object to free.
 123  * @ingroup hcrypto_rsa
 124  */
 125 
 126 void
 127 RSA_free(RSA *rsa)
     /* [<][>][^][v][top][bottom][index][help] */
 128 {
 129     if (rsa->references <= 0)
 130         abort();
 131 
 132     if (--rsa->references > 0)
 133         return;
 134 
 135     (*rsa->meth->finish)(rsa);
 136 
 137     if (rsa->engine)
 138         ENGINE_finish(rsa->engine);
 139 
 140 #define free_if(f) if (f) { BN_free(f); }
 141     free_if(rsa->n);
 142     free_if(rsa->e);
 143     free_if(rsa->d);
 144     free_if(rsa->p);
 145     free_if(rsa->q);
 146     free_if(rsa->dmp1);
 147     free_if(rsa->dmq1);
 148     free_if(rsa->iqmp);
 149 #undef free_if
 150 
 151     memset(rsa, 0, sizeof(*rsa));
 152     free(rsa);
 153 }
 154 
 155 /**
 156  * Add an extra reference to the RSA object. The object should be free
 157  * with RSA_free() to drop the reference.
 158  *
 159  * @param rsa the object to add reference counting too.
 160  *
 161  * @return the current reference count, can't safely be used except
 162  * for debug printing.
 163  *
 164  * @ingroup hcrypto_rsa
 165  */
 166 
 167 int
 168 RSA_up_ref(RSA *rsa)
     /* [<][>][^][v][top][bottom][index][help] */
 169 {
 170     return ++rsa->references;
 171 }
 172 
 173 /**
 174  * Return the RSA_METHOD used for this RSA object.
 175  *
 176  * @param rsa the object to get the method from.
 177  *
 178  * @return the method used for this RSA object.
 179  *
 180  * @ingroup hcrypto_rsa
 181  */
 182 
 183 const RSA_METHOD *
 184 RSA_get_method(const RSA *rsa)
     /* [<][>][^][v][top][bottom][index][help] */
 185 {
 186     return rsa->meth;
 187 }
 188 
 189 /**
 190  * Set a new method for the RSA keypair.
 191  *
 192  * @param rsa rsa parameter.
 193  * @param method the new method for the RSA parameter.
 194  *
 195  * @return 1 on success.
 196  *
 197  * @ingroup hcrypto_rsa
 198  */
 199 
 200 int
 201 RSA_set_method(RSA *rsa, const RSA_METHOD *method)
     /* [<][>][^][v][top][bottom][index][help] */
 202 {
 203     (*rsa->meth->finish)(rsa);
 204 
 205     if (rsa->engine) {
 206         ENGINE_finish(rsa->engine);
 207         rsa->engine = NULL;
 208     }
 209 
 210     rsa->meth = method;
 211     (*rsa->meth->init)(rsa);
 212     return 1;
 213 }
 214 
 215 /**
 216  * Set the application data for the RSA object.
 217  *
 218  * @param rsa the rsa object to set the parameter for
 219  * @param arg the data object to store
 220  *
 221  * @return 1 on success.
 222  *
 223  * @ingroup hcrypto_rsa
 224  */
 225 
 226 int
 227 RSA_set_app_data(RSA *rsa, void *arg)
     /* [<][>][^][v][top][bottom][index][help] */
 228 {
 229     rsa->ex_data.sk = arg;
 230     return 1;
 231 }
 232 
 233 /**
 234  * Get the application data for the RSA object.
 235  *
 236  * @param rsa the rsa object to get the parameter for
 237  *
 238  * @return the data object
 239  *
 240  * @ingroup hcrypto_rsa
 241  */
 242 
 243 void *
 244 RSA_get_app_data(RSA *rsa)
     /* [<][>][^][v][top][bottom][index][help] */
 245 {
 246     return rsa->ex_data.sk;
 247 }
 248 
 249 int
 250 RSA_check_key(const RSA *key)
     /* [<][>][^][v][top][bottom][index][help] */
 251 {
 252     static const unsigned char inbuf[] = "hello, world!";
 253     RSA *rsa = rk_UNCONST(key);
 254     void *buffer;
 255     int ret;
 256 
 257     /*
 258      * XXX I have no clue how to implement this w/o a bignum library.
 259      * Well, when we have a RSA key pair, we can try to encrypt/sign
 260      * and then decrypt/verify.
 261      */
 262 
 263     if ((rsa->d == NULL || rsa->n == NULL) &&
 264         (rsa->p == NULL || rsa->q || rsa->dmp1 == NULL || rsa->dmq1 == NULL || rsa->iqmp == NULL))
 265         return 0;
 266 
 267     buffer = malloc(RSA_size(rsa));
 268     if (buffer == NULL)
 269         return 0;
 270 
 271     ret = RSA_private_encrypt(sizeof(inbuf), inbuf, buffer,
 272                              rsa, RSA_PKCS1_PADDING);
 273     if (ret == -1) {
 274         free(buffer);
 275         return 0;
 276     }
 277 
 278     ret = RSA_public_decrypt(ret, buffer, buffer,
 279                               rsa, RSA_PKCS1_PADDING);
 280     if (ret == -1) {
 281         free(buffer);
 282         return 0;
 283     }
 284 
 285     if (ret == sizeof(inbuf) && memcmp(buffer, inbuf, sizeof(inbuf)) == 0) {
 286         free(buffer);
 287         return 1;
 288     }
 289     free(buffer);
 290     return 0;
 291 }
 292 
 293 int
 294 RSA_size(const RSA *rsa)
     /* [<][>][^][v][top][bottom][index][help] */
 295 {
 296     return BN_num_bytes(rsa->n);
 297 }
 298 
 299 #define RSAFUNC(name, body) \
 300 int \
 301 name(int flen,const unsigned char* f, unsigned char* t, RSA* r, int p){\
 302     return body; \
 303 }
 304 
 305 RSAFUNC(RSA_public_encrypt, (r)->meth->rsa_pub_enc(flen, f, t, r, p))
     /* [<][>][^][v][top][bottom][index][help] */
 306 RSAFUNC(RSA_public_decrypt, (r)->meth->rsa_pub_dec(flen, f, t, r, p))
 307 RSAFUNC(RSA_private_encrypt, (r)->meth->rsa_priv_enc(flen, f, t, r, p))
 308 RSAFUNC(RSA_private_decrypt, (r)->meth->rsa_priv_dec(flen, f, t, r, p))
 309 
 310 /* XXX */
 311 int
 312 RSA_sign(int type, const unsigned char *from, unsigned int flen,
 313          unsigned char *to, unsigned int *tlen, RSA *rsa)
 314 {
 315     return -1;
 316 }
 317 
 318 int
 319 RSA_verify(int type, const unsigned char *from, unsigned int flen,
     /* [<][>][^][v][top][bottom][index][help] */
 320            unsigned char *to, unsigned int tlen, RSA *rsa)
 321 {
 322     return -1;
 323 }
 324 
 325 /*
 326  * A NULL RSA_METHOD that returns failure for all operations. This is
 327  * used as the default RSA method if we don't have any native
 328  * support.
 329  */
 330 
 331 static RSAFUNC(null_rsa_public_encrypt, -1)
     /* [<][>][^][v][top][bottom][index][help] */
 332 static RSAFUNC(null_rsa_public_decrypt, -1)
 333 static RSAFUNC(null_rsa_private_encrypt, -1)
 334 static RSAFUNC(null_rsa_private_decrypt, -1)
 335 
 336 /*
 337  *
 338  */
 339 
 340 int
 341 RSA_generate_key_ex(RSA *r, int bits, BIGNUM *e, BN_GENCB *cb)
 342 {
 343     if (r->meth->rsa_keygen)
 344         return (*r->meth->rsa_keygen)(r, bits, e, cb);
 345     return 0;
 346 }
 347 
 348 
 349 /*
 350  *
 351  */
 352 
 353 static int
 354 null_rsa_init(RSA *rsa)
     /* [<][>][^][v][top][bottom][index][help] */
 355 {
 356     return 1;
 357 }
 358 
 359 static int
 360 null_rsa_finish(RSA *rsa)
     /* [<][>][^][v][top][bottom][index][help] */
 361 {
 362     return 1;
 363 }
 364 
 365 static const RSA_METHOD rsa_null_method = {
 366     "hcrypto null RSA",
 367     null_rsa_public_encrypt,
 368     null_rsa_public_decrypt,
 369     null_rsa_private_encrypt,
 370     null_rsa_private_decrypt,
 371     NULL,
 372     NULL,
 373     null_rsa_init,
 374     null_rsa_finish,
 375     0,
 376     NULL,
 377     NULL,
 378     NULL
 379 };
 380 
 381 const RSA_METHOD *
 382 RSA_null_method(void)
     /* [<][>][^][v][top][bottom][index][help] */
 383 {
 384     return &rsa_null_method;
 385 }
 386 
 387 extern const RSA_METHOD hc_rsa_imath_method;
 388 #ifdef HAVE_GMP
 389 static const RSA_METHOD *default_rsa_method = &hc_rsa_gmp_method;
 390 #else
 391 static const RSA_METHOD *default_rsa_method = &hc_rsa_imath_method;
 392 #endif
 393 
 394 const RSA_METHOD *
 395 RSA_get_default_method(void)
     /* [<][>][^][v][top][bottom][index][help] */
 396 {
 397     return default_rsa_method;
 398 }
 399 
 400 void
 401 RSA_set_default_method(const RSA_METHOD *meth)
     /* [<][>][^][v][top][bottom][index][help] */
 402 {
 403     default_rsa_method = meth;
 404 }
 405 
 406 /*
 407  *
 408  */
 409 
 410 static BIGNUM *
 411 heim_int2BN(const heim_integer *i)
     /* [<][>][^][v][top][bottom][index][help] */
 412 {
 413     BIGNUM *bn;
 414 
 415     bn = BN_bin2bn(i->data, i->length, NULL);
 416     if (bn)
 417         BN_set_negative(bn, i->negative);
 418     return bn;
 419 }
 420 
 421 static int
 422 bn2heim_int(BIGNUM *bn, heim_integer *integer)
     /* [<][>][^][v][top][bottom][index][help] */
 423 {
 424     integer->length = BN_num_bytes(bn);
 425     integer->data = malloc(integer->length);
 426     if (integer->data == NULL) {
 427         integer->length = 0;
 428         return ENOMEM;
 429     }
 430     BN_bn2bin(bn, integer->data);
 431     integer->negative = BN_is_negative(bn);
 432     return 0;
 433 }
 434 
 435 
 436 RSA *
 437 d2i_RSAPrivateKey(RSA *rsa, const unsigned char **pp, size_t len)
     /* [<][>][^][v][top][bottom][index][help] */
 438 {
 439     RSAPrivateKey data;
 440     RSA *k = rsa;
 441     size_t size;
 442     int ret;
 443 
 444     ret = decode_RSAPrivateKey(*pp, len, &data, &size);
 445     if (ret)
 446         return NULL;
 447 
 448     *pp += size;
 449 
 450     if (k == NULL) {
 451         k = RSA_new();
 452         if (k == NULL) {
 453             free_RSAPrivateKey(&data);
 454             return NULL;
 455         }
 456     }
 457 
 458     k->n = heim_int2BN(&data.modulus);
 459     k->e = heim_int2BN(&data.publicExponent);
 460     k->d = heim_int2BN(&data.privateExponent);
 461     k->p = heim_int2BN(&data.prime1);
 462     k->q = heim_int2BN(&data.prime2);
 463     k->dmp1 = heim_int2BN(&data.exponent1);
 464     k->dmq1 = heim_int2BN(&data.exponent2);
 465     k->iqmp = heim_int2BN(&data.coefficient);
 466     free_RSAPrivateKey(&data);
 467 
 468     if (k->n == NULL || k->e == NULL || k->d == NULL || k->p == NULL ||
 469         k->q == NULL || k->dmp1 == NULL || k->dmq1 == NULL || k->iqmp == NULL)
 470     {
 471         RSA_free(k);
 472         return NULL;
 473     }
 474         
 475     return k;
 476 }
 477 
 478 int
 479 i2d_RSAPrivateKey(RSA *rsa, unsigned char **pp)
     /* [<][>][^][v][top][bottom][index][help] */
 480 {
 481     RSAPrivateKey data;
 482     size_t size;
 483     int ret;
 484 
 485     if (rsa->n == NULL || rsa->e == NULL || rsa->d == NULL || rsa->p == NULL ||
 486         rsa->q == NULL || rsa->dmp1 == NULL || rsa->dmq1 == NULL ||
 487         rsa->iqmp == NULL)
 488         return -1;
 489 
 490     memset(&data, 0, sizeof(data));
 491 
 492     ret  = bn2heim_int(rsa->n, &data.modulus);
 493     ret |= bn2heim_int(rsa->e, &data.publicExponent);
 494     ret |= bn2heim_int(rsa->d, &data.privateExponent);
 495     ret |= bn2heim_int(rsa->p, &data.prime1);
 496     ret |= bn2heim_int(rsa->q, &data.prime2);
 497     ret |= bn2heim_int(rsa->dmp1, &data.exponent1);
 498     ret |= bn2heim_int(rsa->dmq1, &data.exponent2);
 499     ret |= bn2heim_int(rsa->iqmp, &data.coefficient);
 500     if (ret) {
 501         free_RSAPrivateKey(&data);
 502         return -1;
 503     }
 504 
 505     if (pp == NULL) {
 506         size = length_RSAPrivateKey(&data);
 507         free_RSAPrivateKey(&data);
 508     } else {
 509         void *p;
 510         size_t len;
 511 
 512         ASN1_MALLOC_ENCODE(RSAPrivateKey, p, len, &data, &size, ret);
 513         free_RSAPrivateKey(&data);
 514         if (ret)
 515             return -1;
 516         if (len != size)
 517             abort();
 518 
 519         memcpy(*pp, p, size);
 520         free(p);
 521 
 522         *pp += size;
 523 
 524     }
 525     return size;
 526 }
 527 
 528 int
 529 i2d_RSAPublicKey(RSA *rsa, unsigned char **pp)
     /* [<][>][^][v][top][bottom][index][help] */
 530 {
 531     RSAPublicKey data;
 532     size_t size;
 533     int ret;
 534 
 535     memset(&data, 0, sizeof(data));
 536 
 537     if (bn2heim_int(rsa->n, &data.modulus) ||
 538         bn2heim_int(rsa->e, &data.publicExponent))
 539     {
 540         free_RSAPublicKey(&data);
 541         return -1;
 542     }
 543 
 544     if (pp == NULL) {
 545         size = length_RSAPublicKey(&data);
 546         free_RSAPublicKey(&data);
 547     } else {
 548         void *p;
 549         size_t len;
 550 
 551         ASN1_MALLOC_ENCODE(RSAPublicKey, p, len, &data, &size, ret);
 552         free_RSAPublicKey(&data);
 553         if (ret)
 554             return -1;
 555         if (len != size)
 556             abort();
 557 
 558         memcpy(*pp, p, size);
 559         free(p);
 560 
 561         *pp += size;
 562     }
 563 
 564     return size;
 565 }

/* [<][>][^][v][top][bottom][index][help] */