LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/hcrypto - rsa-ltm.c (source / functions) Hit Total Coverage
Test: coverage report for vadcx-master-patch-75612 fe003de8 Lines: 183 355 51.5 %
Date: 2024-02-29 22:57:05 Functions: 11 16 68.8 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2006 - 2007, 2010 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             : #include <config.h>
      35             : #include <roken.h>
      36             : #include <krb5-types.h>
      37             : #include <assert.h>
      38             : 
      39             : #include <rsa.h>
      40             : 
      41             : #include "tommath.h"
      42             : 
      43             : #define CHECK(f)                                                        \
      44             :     do { where = __LINE__ + 1; if (ret == MP_OKAY && ((ret = f)) != MP_OKAY) { goto out; } } while (0)
      45             : #define FIRST(e) do { ret = (e); } while (0)
      46             : #define FIRST_ALLOC(e)                                                  \
      47             :     do { where = __LINE__; ret = ((e)) ? MP_OKAY : MP_MEM; } while (0)
      48             : #define THEN_MP(e)                                                      \
      49             :     do { where = __LINE__ + 1; if (ret == MP_OKAY) ret = (e); } while (0)
      50             : #define THEN_IF_MP(cond, e)                                             \
      51             :     do { where = __LINE__ + 1; if (ret == MP_OKAY && (cond)) ret = (e); } while (0)
      52             : #define THEN_IF_VOID(cond, e)                                           \
      53             :     do { where = __LINE__ + 1; if (ret == MP_OKAY && (cond)) e; } while (0)
      54             : #define THEN_VOID(e)                                                    \
      55             :     do { where = __LINE__ + 1; if (ret == MP_OKAY) e; } while (0)
      56             : #define THEN_ALLOC(e)                                                   \
      57             :     do { where = __LINE__ + 1; if (ret == MP_OKAY) ret = ((e)) ? MP_OKAY : MP_MEM; } while (0)
      58             : 
      59             : static mp_err
      60         135 : random_num(mp_int *num, size_t len)
      61             : {
      62           8 :     unsigned char *p;
      63         135 :     mp_err ret = MP_MEM;
      64             : 
      65         135 :     len = (len + 7) / 8; /* bits to bytes */
      66         135 :     if ((p = malloc(len)) && RAND_bytes(p, len) != 1)
      67           0 :         ret = MP_ERR;
      68         135 :     if (p)
      69         135 :         ret = mp_from_ubin(num, p, len);
      70         135 :     free(p);
      71         135 :     return ret;
      72             : }
      73             : 
      74             : static mp_err
      75        1551 : BN2mpz(mp_int *s, const BIGNUM *bn)
      76             : {
      77          72 :     size_t len;
      78        1551 :     mp_err ret = MP_MEM;
      79          72 :     void *p;
      80             : 
      81        1551 :     len = BN_num_bytes(bn);
      82        1551 :     p = malloc(len);
      83        1551 :     if (p) {
      84        1551 :         BN_bn2bin(bn, p);
      85        1551 :         ret = mp_from_ubin(s, p, len);
      86             :     }
      87        1551 :     free(p);
      88        1551 :     return ret;
      89             : }
      90             : 
      91             : static mp_err
      92         135 : setup_blind(mp_int *n, mp_int *b, mp_int *bi)
      93             : {
      94           8 :     mp_err ret;
      95             : 
      96         135 :     ret = random_num(b, mp_count_bits(n));
      97         135 :     if (ret == MP_OKAY) ret = mp_mod(b, n, b);
      98         135 :     if (ret == MP_OKAY) ret = mp_invmod(b, n, bi);
      99         135 :     return ret;
     100             : }
     101             : 
     102             : static mp_err
     103         135 : blind(mp_int *in, mp_int *b, mp_int *e, mp_int *n)
     104             : {
     105           8 :     mp_err ret;
     106           8 :     mp_int t1;
     107             : 
     108         135 :     ret = mp_init(&t1);
     109             :     /* in' = (in * b^e) mod n */
     110         135 :     if (ret == MP_OKAY) ret = mp_exptmod(b, e, n, &t1);
     111         135 :     if (ret == MP_OKAY) ret = mp_mul(&t1, in, in);
     112         135 :     if (ret == MP_OKAY) ret = mp_mod(in, n, in);
     113         135 :     mp_clear(&t1);
     114         135 :     return ret;
     115             : }
     116             : 
     117             : static mp_err
     118         135 : unblind(mp_int *out, mp_int *bi, mp_int *n)
     119             : {
     120           8 :     mp_err ret;
     121             : 
     122             :     /* out' = (out * 1/b) mod n */
     123         135 :     ret = mp_mul(out, bi, out);
     124         135 :     if (ret == MP_OKAY) ret = mp_mod(out, n, out);
     125         135 :     return ret;
     126             : }
     127             : 
     128             : static mp_err
     129         135 : ltm_rsa_private_calculate(mp_int * in, mp_int * p,  mp_int * q,
     130             :                           mp_int * dmp1, mp_int * dmq1, mp_int * iqmp,
     131             :                           mp_int * out)
     132             : {
     133           8 :     mp_err ret;
     134           8 :     mp_int vp, vq, u;
     135         135 :     int where HEIMDAL_UNUSED_ATTRIBUTE = 0;
     136             : 
     137         135 :     FIRST(mp_init_multi(&vp, &vq, &u, NULL));
     138             : 
     139             :     /* vq = c ^ (d mod (q - 1)) mod q */
     140             :     /* vp = c ^ (d mod (p - 1)) mod p */
     141         135 :     THEN_MP(mp_mod(in, p, &u));
     142         135 :     THEN_MP(mp_exptmod(&u, dmp1, p, &vp));
     143         135 :     THEN_MP(mp_mod(in, q, &u));
     144         135 :     THEN_MP(mp_exptmod(&u, dmq1, q, &vq));
     145             : 
     146             :     /* C2 = 1/q mod p  (iqmp) */
     147             :     /* u = (vp - vq)C2 mod p. */
     148         135 :     THEN_MP(mp_sub(&vp, &vq, &u));
     149         135 :     THEN_IF_MP(mp_isneg(&u), mp_add(&u, p, &u));
     150         135 :     THEN_MP(mp_mul(&u, iqmp, &u));
     151         135 :     THEN_MP(mp_mod(&u, p, &u));
     152             : 
     153             :     /* c ^ d mod n = vq + u q */
     154         135 :     THEN_MP(mp_mul(&u, q, &u));
     155         135 :     THEN_MP(mp_add(&u, &vq, out));
     156             : 
     157         135 :     mp_clear_multi(&vp, &vq, &u, NULL);
     158         135 :     return ret;
     159             : }
     160             : 
     161             : /*
     162             :  *
     163             :  */
     164             : 
     165             : static int
     166          17 : ltm_rsa_public_encrypt(int flen, const unsigned char* from,
     167             :                         unsigned char* to, RSA* rsa, int padding)
     168             : {
     169          17 :     unsigned char *p = NULL, *p0 = NULL;
     170          17 :     size_t size, ssize = 0, padlen;
     171           0 :     mp_int enc, dec, n, e;
     172           0 :     mp_err ret;
     173          17 :     int where = __LINE__;
     174             : 
     175          17 :     if (padding != RSA_PKCS1_PADDING)
     176           0 :         return -1;
     177             : 
     178          17 :     FIRST(mp_init_multi(&n, &e, &enc, &dec, NULL));
     179             : 
     180          17 :     size = RSA_size(rsa);
     181          17 :     THEN_IF_MP((size < RSA_PKCS1_PADDING_SIZE ||
     182             :                 size - RSA_PKCS1_PADDING_SIZE < flen),
     183             :                MP_ERR);
     184          17 :     THEN_MP(BN2mpz(&n, rsa->n));
     185          17 :     THEN_MP(BN2mpz(&e, rsa->e));
     186          17 :     THEN_IF_MP((mp_cmp_d(&e, 3) == MP_LT), MP_ERR);
     187          17 :     THEN_ALLOC((p = p0 = malloc(size - 1)));
     188             : 
     189          17 :     if (ret == MP_OKAY) {
     190          17 :         padlen = size - flen - 3;
     191          17 :         *p++ = 2;
     192             :     }
     193          17 :     THEN_IF_MP((RAND_bytes(p, padlen) != 1), MP_ERR);
     194             : 
     195          17 :     if (ret == MP_OKAY) {
     196        3806 :         while (padlen) {
     197        3789 :             if (*p == 0)
     198          10 :                 *p = 1;
     199        3789 :             padlen--;
     200        3789 :             p++;
     201             :         }
     202          17 :         *p++ = 0;
     203          17 :         memcpy(p, from, flen);
     204          17 :         p += flen;
     205          17 :         assert((p - p0) == size - 1);
     206             :     }
     207             : 
     208          17 :     THEN_MP(mp_from_ubin(&dec, p0, size - 1));
     209          17 :     THEN_MP(mp_exptmod(&dec, &e, &n, &enc));
     210          17 :     THEN_VOID(ssize = mp_ubin_size(&enc));
     211          17 :     THEN_VOID(assert(size >= ssize));
     212          17 :     THEN_MP(mp_to_ubin(&enc, to, SIZE_MAX, NULL));
     213          17 :     THEN_VOID(size = ssize);
     214             : 
     215          17 :     mp_clear_multi(&dec, &e, &n, NULL);
     216          17 :     mp_clear(&enc);
     217          17 :     free(p0);
     218          17 :     return ret == MP_OKAY ? size : -where;
     219             : }
     220             : 
     221             : static int
     222         286 : ltm_rsa_public_decrypt(int flen, const unsigned char* from,
     223             :                        unsigned char* to, RSA* rsa, int padding)
     224             : {
     225         286 :     unsigned char *p = NULL;
     226           8 :     mp_err ret;
     227         286 :     size_t size = 0;
     228           8 :     mp_int s, us, n, e;
     229         286 :     int where = __LINE__;
     230             : 
     231         286 :     if (padding != RSA_PKCS1_PADDING)
     232           0 :         return -1;
     233             : 
     234         286 :     if (flen > RSA_size(rsa))
     235           0 :         return -2;
     236             : 
     237         286 :     FIRST(mp_init_multi(&e, &n, &s, &us, NULL));
     238         286 :     THEN_MP(BN2mpz(&n, rsa->n));
     239         286 :     THEN_MP(BN2mpz(&e, rsa->e));
     240         286 :     THEN_MP((mp_cmp_d(&e, 3) == MP_LT) ? MP_ERR : MP_OKAY);
     241         286 :     THEN_MP(mp_from_ubin(&s, rk_UNCONST(from), (size_t)flen));
     242         286 :     THEN_MP((mp_cmp(&s, &n) >= 0) ? MP_ERR : MP_OKAY);
     243         286 :     THEN_MP(mp_exptmod(&s, &e, &n, &us));
     244             : 
     245         286 :     THEN_VOID(p = to);
     246         286 :     THEN_VOID(size = mp_ubin_size(&us));
     247         286 :     THEN_VOID(assert(size <= RSA_size(rsa)));
     248         286 :     THEN_MP(mp_to_ubin(&us, p, SIZE_MAX, NULL));
     249             : 
     250         286 :     mp_clear_multi(&e, &n, &s, NULL);
     251         286 :     mp_clear(&us);
     252             : 
     253         286 :     if (ret != MP_OKAY || size == 0)
     254           0 :         return -where;
     255             : 
     256             :     /* head zero was skipped by mp_to_unsigned_bin */
     257         286 :     if (*p == 0)
     258           0 :         return -where;
     259         286 :     if (*p != 1)
     260           0 :         return -(where + 1);
     261         286 :     size--; p++;
     262      186732 :     while (size && *p == 0xff) {
     263      186446 :         size--; p++;
     264             :     }
     265         286 :     if (size == 0 || *p != 0)
     266           0 :         return -(where + 2);
     267         286 :     size--; p++;
     268         286 :     memmove(to, p, size);
     269         286 :     return size;
     270             : }
     271             : 
     272             : static int
     273         135 : ltm_rsa_private_encrypt(int flen, const unsigned char* from,
     274             :                         unsigned char* to, RSA* rsa, int padding)
     275             : {
     276         135 :     unsigned char *ptr = NULL, *ptr0 = NULL;
     277           8 :     mp_err ret;
     278           8 :     mp_int in, out, n, e;
     279           8 :     mp_int bi, b;
     280           8 :     size_t size;
     281         135 :     int blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0;
     282         135 :     int do_unblind = 0;
     283         135 :     int where = __LINE__;
     284             : 
     285         135 :     if (padding != RSA_PKCS1_PADDING)
     286           0 :         return -1;
     287             : 
     288         135 :     FIRST(mp_init_multi(&e, &n, &in, &out, &b, &bi, NULL));
     289             : 
     290         135 :     size = RSA_size(rsa);
     291         135 :     if (size < RSA_PKCS1_PADDING_SIZE || size - RSA_PKCS1_PADDING_SIZE < flen)
     292           0 :         return -2;
     293             : 
     294         135 :     THEN_ALLOC((ptr0 = ptr = malloc(size)));
     295         135 :     if (ret == MP_OKAY) {
     296         135 :         *ptr++ = 0;
     297         135 :         *ptr++ = 1;
     298         135 :         memset(ptr, 0xff, size - flen - 3);
     299         135 :         ptr += size - flen - 3;
     300         135 :         *ptr++ = 0;
     301         135 :         memcpy(ptr, from, flen);
     302         135 :         ptr += flen;
     303         135 :         assert((ptr - ptr0) == size);
     304             :     }
     305             : 
     306         135 :     THEN_MP(BN2mpz(&n, rsa->n));
     307         135 :     THEN_MP(BN2mpz(&e, rsa->e));
     308         135 :     THEN_IF_MP((mp_cmp_d(&e, 3) == MP_LT), MP_ERR);
     309         135 :     THEN_MP(mp_from_ubin(&in, ptr0, size));
     310         135 :     free(ptr0);
     311             : 
     312         135 :     THEN_IF_MP((mp_isneg(&in) || mp_cmp(&in, &n) >= 0), MP_ERR);
     313             : 
     314         135 :     if (blinding) {
     315         135 :         THEN_MP(setup_blind(&n, &b, &bi));
     316         135 :         THEN_MP(blind(&in, &b, &e, &n));
     317         127 :         do_unblind = 1;
     318             :     }
     319             : 
     320         135 :     if (ret == MP_OKAY && rsa->p && rsa->q && rsa->dmp1 && rsa->dmq1 &&
     321         270 :         rsa->iqmp) {
     322           8 :         mp_int p, q, dmp1, dmq1, iqmp;
     323             : 
     324         135 :         FIRST(mp_init_multi(&p, &q, &dmp1, &dmq1, &iqmp, NULL));
     325         135 :         THEN_MP(BN2mpz(&p, rsa->p));
     326         135 :         THEN_MP(BN2mpz(&q, rsa->q));
     327         135 :         THEN_MP(BN2mpz(&dmp1, rsa->dmp1));
     328         135 :         THEN_MP(BN2mpz(&dmq1, rsa->dmq1));
     329         135 :         THEN_MP(BN2mpz(&iqmp, rsa->iqmp));
     330         135 :         THEN_MP(ltm_rsa_private_calculate(&in, &p, &q, &dmp1, &dmq1, &iqmp,
     331             :                                           &out));
     332         135 :         mp_clear_multi(&p, &q, &dmp1, &dmq1, &iqmp, NULL);
     333         135 :         if (ret != MP_OKAY) goto out;
     334           0 :     } else if (ret == MP_OKAY) {
     335           0 :         mp_int d;
     336             : 
     337           0 :         THEN_MP(BN2mpz(&d, rsa->d));
     338           0 :         THEN_MP(mp_exptmod(&in, &d, &n, &out));
     339           0 :         mp_clear(&d);
     340           0 :         if (ret != MP_OKAY) goto out;
     341             :     }
     342             : 
     343         135 :     if (do_unblind)
     344         135 :         THEN_MP(unblind(&out, &bi, &n));
     345             : 
     346         135 :     if (ret == MP_OKAY && size > 0) {
     347           8 :         size_t ssize;
     348             : 
     349         135 :         ssize = mp_ubin_size(&out);
     350         135 :         assert(size >= ssize);
     351         135 :         THEN_MP(mp_to_ubin(&out, to, SIZE_MAX, NULL));
     352         135 :         size = ssize;
     353             :     }
     354             : 
     355           0 :  out:
     356         135 :     mp_clear_multi(&e, &n, &in, &out, &b, &bi, NULL);
     357         135 :     return ret == MP_OKAY ? size : -where;
     358             : }
     359             : 
     360             : static int
     361           0 : ltm_rsa_private_decrypt(int flen, const unsigned char* from,
     362             :                         unsigned char* to, RSA* rsa, int padding)
     363             : {
     364           0 :     unsigned char *ptr;
     365           0 :     size_t size;
     366           0 :     mp_err ret;
     367           0 :     mp_int in, out, n, e, b, bi;
     368           0 :     int blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0;
     369           0 :     int do_unblind = 0;
     370           0 :     int where = __LINE__;
     371             : 
     372           0 :     if (padding != RSA_PKCS1_PADDING)
     373           0 :         return -1;
     374             : 
     375           0 :     size = RSA_size(rsa);
     376           0 :     if (flen > size)
     377           0 :         return -2;
     378             : 
     379           0 :     FIRST(mp_init_multi(&in, &n, &e, &out, &b, &bi, NULL));
     380           0 :     THEN_MP(BN2mpz(&n, rsa->n));
     381           0 :     THEN_MP(BN2mpz(&e, rsa->e));
     382           0 :     THEN_IF_MP((mp_cmp_d(&e, 3) == MP_LT), MP_ERR);
     383           0 :     THEN_MP(mp_from_ubin(&in, rk_UNCONST(from), flen));
     384           0 :     THEN_IF_MP((mp_isneg(&in) || mp_cmp(&in, &n) >= 0), MP_ERR);
     385             : 
     386           0 :     if (blinding) {
     387           0 :         THEN_MP(setup_blind(&n, &b, &bi));
     388           0 :         THEN_MP(blind(&in, &b, &e, &n));
     389           0 :         do_unblind = 1;
     390             :     }
     391             : 
     392           0 :     if (ret == MP_OKAY && rsa->p && rsa->q && rsa->dmp1 && rsa->dmq1 &&
     393           0 :         rsa->iqmp) {
     394           0 :         mp_int p, q, dmp1, dmq1, iqmp;
     395             : 
     396           0 :         THEN_MP(mp_init_multi(&p, &q, &dmp1, &dmq1, &iqmp, NULL));
     397           0 :         THEN_MP(BN2mpz(&p, rsa->p));
     398           0 :         THEN_MP(BN2mpz(&q, rsa->q));
     399           0 :         THEN_MP(BN2mpz(&dmp1, rsa->dmp1));
     400           0 :         THEN_MP(BN2mpz(&dmq1, rsa->dmq1));
     401           0 :         THEN_MP(BN2mpz(&iqmp, rsa->iqmp));
     402           0 :         THEN_MP(ltm_rsa_private_calculate(&in, &p, &q, &dmp1, &dmq1, &iqmp, &out));
     403           0 :         mp_clear_multi(&p, &q, &dmp1, &dmq1, &iqmp, NULL);
     404           0 :         if (ret != MP_OKAY) goto out;
     405           0 :     } else if (ret == MP_OKAY) {
     406           0 :         mp_int d;
     407             : 
     408           0 :         THEN_IF_MP((mp_isneg(&in) || mp_cmp(&in, &n) >= 0), MP_ERR);
     409           0 :         THEN_MP(BN2mpz(&d, rsa->d));
     410           0 :         THEN_MP(mp_exptmod(&in, &d, &n, &out));
     411           0 :         mp_clear(&d);
     412           0 :         if (ret != MP_OKAY) goto out;
     413             :     }
     414             : 
     415           0 :     if (do_unblind)
     416           0 :         THEN_MP(unblind(&out, &bi, &n));
     417             : 
     418           0 :     if (ret == MP_OKAY) {
     419           0 :         size_t ssize;
     420             : 
     421           0 :         ptr = to;
     422           0 :         ssize = mp_ubin_size(&out);
     423           0 :         assert(size >= ssize);
     424           0 :         ret = mp_to_ubin(&out, ptr, SIZE_MAX, NULL);
     425           0 :         if (ret != MP_OKAY) goto out;
     426           0 :         size = ssize;
     427             : 
     428             :         /* head zero was skipped by mp_int_to_unsigned */
     429           0 :         if (*ptr != 2) {
     430           0 :             where = __LINE__;
     431           0 :             goto out;
     432             :         }
     433           0 :         size--; ptr++;
     434           0 :         while (size && *ptr != 0) {
     435           0 :             size--; ptr++;
     436             :         }
     437           0 :         if (size == 0) {
     438           0 :             where = __LINE__;
     439           0 :             goto out;
     440             :         }
     441           0 :         size--; ptr++;
     442           0 :         memmove(to, ptr, size);
     443             :     }
     444             : 
     445           0 :  out:
     446           0 :     mp_clear_multi(&e, &n, &in, &out, &b, &bi, NULL);
     447           0 :     return (ret == MP_OKAY) ? size : -where;
     448             : }
     449             : 
     450             : static BIGNUM *
     451           0 : mpz2BN(mp_int *s)
     452             : {
     453           0 :     size_t size;
     454           0 :     BIGNUM *bn;
     455           0 :     mp_err ret;
     456           0 :     void *p;
     457             : 
     458           0 :     size = mp_ubin_size(s);
     459           0 :     if (size == 0)
     460           0 :         return NULL;
     461             : 
     462           0 :     p = malloc(size);
     463           0 :     if (p == NULL)
     464           0 :         return NULL;
     465             : 
     466           0 :     ret = mp_to_ubin(s, p, SIZE_MAX, NULL);
     467           0 :     if (ret == MP_OKAY)
     468           0 :         bn = BN_bin2bn(p, size, NULL);
     469           0 :     free(p);
     470           0 :     return (ret == MP_OKAY) ? bn : NULL;
     471             : }
     472             : 
     473             : enum gen_pq_type { GEN_P, GEN_Q };
     474             : 
     475             : static int
     476           0 : gen_p(int bits, enum gen_pq_type pq_type, uint8_t nibble_pair, mp_int *p, mp_int *e, BN_GENCB *cb)
     477             : {
     478           0 :     unsigned char *buf = NULL;
     479           0 :     mp_bool res;
     480           0 :     mp_err ret = MP_MEM;
     481           0 :     mp_int t1, t2;
     482           0 :     size_t len = (bits + 7) / 8;
     483           0 :     int trials = mp_prime_rabin_miller_trials(bits);
     484           0 :     int counter = 0;
     485           0 :     int where HEIMDAL_UNUSED_ATTRIBUTE = 0;
     486             : 
     487             : 
     488           0 :     FIRST(mp_init_multi(&t1, &t2, NULL));
     489           0 :     if (ret == MP_OKAY && (buf = malloc(len))) do {
     490           0 :         BN_GENCB_call(cb, 2, counter++);
     491             :         /* random bytes */
     492           0 :         ret = (RAND_bytes(buf, len) == 1) ? MP_OKAY : MP_ERR;
     493             : 
     494             :         /* make it odd */
     495           0 :         buf[len - 1] |= 1;
     496             : 
     497             :         /* ensure the high nibble of the product is at least 128 */
     498           0 :         if (pq_type == GEN_P)
     499           0 :             buf[0] = (nibble_pair & 0xf0)         | (buf[0] & 0x0f);
     500             :         else
     501           0 :             buf[0] = ((nibble_pair & 0x0f) << 4)  | (buf[0] & 0x0f);
     502             : 
     503             :         /* load number */
     504           0 :         THEN_MP(mp_from_ubin(p, buf, len));
     505             : 
     506             :         /* test primality; repeat if not */
     507           0 :         THEN_MP(mp_prime_is_prime(p, trials, &res));
     508           0 :         if (ret == MP_OKAY && res == MP_NO) continue;
     509             : 
     510             :         /* check gcd(p - 1, e) == 1 */
     511           0 :         THEN_MP(mp_sub_d(p, 1, &t1));
     512           0 :         THEN_MP(mp_gcd(&t1, e, &t2));
     513           0 :     } while (ret == MP_OKAY && mp_cmp_d(&t2, 1) != MP_EQ);
     514             : 
     515           0 :     mp_clear_multi(&t1, &t2, NULL);
     516           0 :     free(buf);
     517           0 :     return ret;
     518             : }
     519             : 
     520             : static uint8_t pq_high_nibble_pairs[] = {
     521             : 0x9f, 0xad, 0xae, 0xaf, 0xbc, 0xbd, 0xbe, 0xbf, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
     522             : 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf9,
     523             : 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
     524             : };
     525             : 
     526             : static int
     527           0 : ltm_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)
     528             : {
     529           0 :     mp_int el, p, q, n, d, dmp1, dmq1, iqmp, t1, t2, t3;
     530           0 :     mp_err ret;
     531           0 :     uint8_t high_nibbles = 0;
     532           0 :     int bitsp;
     533           0 :     int where = __LINE__;
     534             : 
     535           0 :     if (bits < 789)
     536           0 :         return -1;
     537             : 
     538           0 :     bitsp = (bits + 1) / 2;
     539             : 
     540           0 :     FIRST(mp_init_multi(&el, &p, &q, &n, &d,
     541             :                         &dmp1, &dmq1, &iqmp,
     542             :                         &t1, &t2, &t3, NULL));
     543           0 :     THEN_MP(BN2mpz(&el, e));
     544             : 
     545             :     /*
     546             :      * randomly pick a pair of high nibbles for p and q to ensure the product's
     547             :      * high nibble is at least 128
     548             :      */
     549           0 :     if (ret == MP_OKAY)
     550           0 :         ret = (RAND_bytes(&high_nibbles, 1) == 1) ? MP_OKAY : MP_ERR;
     551           0 :     high_nibbles %= sizeof(pq_high_nibble_pairs);
     552           0 :     high_nibbles = pq_high_nibble_pairs[high_nibbles];
     553             : 
     554             :     /* generate p and q so that p != q and bits(pq) ~ bits */
     555           0 :     THEN_MP(gen_p(bitsp, GEN_P, high_nibbles, &p, &el, cb));
     556           0 :     BN_GENCB_call(cb, 3, 0);
     557           0 :     THEN_MP(gen_p(bitsp, GEN_Q, high_nibbles, &q, &el, cb));
     558             : 
     559             :     /* make p > q */
     560           0 :     if (mp_cmp(&p, &q) < 0) {
     561           0 :         mp_int c;
     562           0 :         c = p;
     563           0 :         p = q;
     564           0 :         q = c;
     565             :     }
     566             : 
     567           0 :     BN_GENCB_call(cb, 3, 1);
     568             : 
     569             :     /* calculate n,             n = p * q */
     570           0 :     THEN_MP(mp_mul(&p, &q, &n));
     571             : 
     572             :     /* calculate d,             d = 1/e mod (p - 1)(q - 1) */
     573           0 :     THEN_MP(mp_sub_d(&p, 1, &t1));
     574           0 :     THEN_MP(mp_sub_d(&q, 1, &t2));
     575           0 :     THEN_MP(mp_mul(&t1, &t2, &t3));
     576           0 :     THEN_MP(mp_invmod(&el, &t3, &d));
     577             : 
     578             :     /* calculate dmp1           dmp1 = d mod (p-1) */
     579           0 :     THEN_MP(mp_mod(&d, &t1, &dmp1));
     580             :     /* calculate dmq1           dmq1 = d mod (q-1) */
     581           0 :     THEN_MP(mp_mod(&d, &t2, &dmq1));
     582             :     /* calculate iqmp           iqmp = 1/q mod p */
     583           0 :     THEN_MP(mp_invmod(&q, &p, &iqmp));
     584             : 
     585             :     /* fill in RSA key */
     586             : 
     587           0 :     if (ret == MP_OKAY) {
     588           0 :         rsa->e = mpz2BN(&el);
     589           0 :         rsa->p = mpz2BN(&p);
     590           0 :         rsa->q = mpz2BN(&q);
     591           0 :         rsa->n = mpz2BN(&n);
     592           0 :         rsa->d = mpz2BN(&d);
     593           0 :         rsa->dmp1 = mpz2BN(&dmp1);
     594           0 :         rsa->dmq1 = mpz2BN(&dmq1);
     595           0 :         rsa->iqmp = mpz2BN(&iqmp);
     596             :     }
     597             : 
     598           0 :     mp_clear_multi(&el, &p, &q, &n, &d,
     599             :                    &dmp1, &dmq1, &iqmp,
     600             :                    &t1, &t2, &t3, NULL);
     601           0 :     return (ret == MP_OKAY) ? 1 : -where;
     602             : }
     603             : 
     604             : static int
     605         377 : ltm_rsa_init(RSA *rsa)
     606             : {
     607         377 :     return 1;
     608             : }
     609             : 
     610             : static int
     611         323 : ltm_rsa_finish(RSA *rsa)
     612             : {
     613         323 :     return 1;
     614             : }
     615             : 
     616             : const RSA_METHOD hc_rsa_ltm_method = {
     617             :     "hcrypto ltm RSA",
     618             :     ltm_rsa_public_encrypt,
     619             :     ltm_rsa_public_decrypt,
     620             :     ltm_rsa_private_encrypt,
     621             :     ltm_rsa_private_decrypt,
     622             :     NULL,
     623             :     NULL,
     624             :     ltm_rsa_init,
     625             :     ltm_rsa_finish,
     626             :     0,
     627             :     NULL,
     628             :     NULL,
     629             :     NULL,
     630             :     ltm_rsa_generate_key
     631             : };
     632             : 
     633             : const RSA_METHOD *
     634           0 : RSA_ltm_method(void)
     635             : {
     636           0 :     return &hc_rsa_ltm_method;
     637             : }

Generated by: LCOV version 1.14