busybox/networking/tls_rsa.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2017 Denys Vlasenko
   3 *
   4 * Licensed under GPLv2, see file LICENSE in this source tree.
   5 */
   6#include "tls.h"
   7
   8/* The code below is taken from parts of
   9 *  matrixssl-3-7-2b-open/crypto/pubkey/pkcs.c
  10 *  matrixssl-3-7-2b-open/crypto/pubkey/rsa.c
  11 * and (so far) almost not modified. Changes are flagged with //bbox
  12 */
  13
  14#define pkcs1Pad(in, inlen, out, outlen, cryptType, userPtr) \
  15        pkcs1Pad(in, inlen, out, outlen, cryptType)
  16static //bbox
  17int32 pkcs1Pad(unsigned char *in, uint32 inlen, unsigned char *out,
  18                        uint32 outlen, int32 cryptType, void *userPtr)
  19{
  20        unsigned char   *c;
  21        int32           randomLen;
  22
  23        randomLen = outlen - 3 - inlen;
  24        if (randomLen < 8) {
  25                psTraceCrypto("pkcs1Pad failure\n");
  26                return PS_LIMIT_FAIL;
  27        }
  28        c = out;
  29        *c = 0x00;
  30        c++;
  31        *c = (unsigned char)cryptType;
  32        c++;
  33        if (cryptType == PUBKEY_TYPE) {
  34                while (randomLen-- > 0) {
  35                        *c++ = 0xFF;
  36                }
  37        } else {
  38                if (matrixCryptoGetPrngData(c, (uint32)randomLen, userPtr) < 0) {
  39                        return PS_PLATFORM_FAIL;
  40                }
  41/*
  42                SECURITY:  Read through the random data and change all 0x0 to 0x01.
  43                This is per spec that no random bytes should be 0
  44*/
  45                while (randomLen-- > 0) {
  46                        if (*c == 0x0) {
  47                                *c = 0x01;
  48                        }
  49                        c++;
  50                }
  51        }
  52        *c = 0x00;
  53        c++;
  54        memcpy(c, in, inlen);
  55
  56        return outlen;
  57}
  58
  59#define psRsaCrypt(pool, in, inlen, out, outlen, key, type, data) \
  60        psRsaCrypt(      in, inlen, out, outlen, key, type)
  61static //bbox
  62int32 psRsaCrypt(psPool_t *pool, const unsigned char *in, uint32 inlen,
  63                        unsigned char *out, uint32 *outlen, psRsaKey_t *key, int32 type,
  64                        void *data)
  65{
  66        pstm_int                tmp, tmpa, tmpb;
  67        int32                   res;
  68        uint32                  x;
  69
  70//bbox
  71//      if (in == NULL || out == NULL || outlen == NULL || key == NULL) {
  72//              psTraceCrypto("NULL parameter error in psRsaCrypt\n");
  73//              return PS_ARG_FAIL;
  74//      }
  75
  76        tmp.dp = tmpa.dp = tmpb.dp = NULL;
  77
  78        /* Init and copy into tmp */
  79        if (pstm_init_for_read_unsigned_bin(pool, &tmp, inlen + sizeof(pstm_digit))
  80                        != PS_SUCCESS) {
  81                return PS_FAILURE;
  82        }
  83        if (pstm_read_unsigned_bin(&tmp, (unsigned char *)in, inlen) != PS_SUCCESS){
  84                pstm_clear(&tmp);
  85                return PS_FAILURE;
  86        }
  87        /* Sanity check on the input */
  88        if (pstm_cmp(&key->N, &tmp) == PSTM_LT) {
  89                res = PS_LIMIT_FAIL;
  90                goto done;
  91        }
  92        if (type == PRIVKEY_TYPE) {
  93                if (key->optimized) {
  94                        if (pstm_init_size(pool, &tmpa, key->p.alloc) != PS_SUCCESS) {
  95                                res = PS_FAILURE;
  96                                goto done;
  97                        }
  98                        if (pstm_init_size(pool, &tmpb, key->q.alloc) != PS_SUCCESS) {
  99                                pstm_clear(&tmpa);
 100                                res = PS_FAILURE;
 101                                goto done;
 102                        }
 103                        if (pstm_exptmod(pool, &tmp, &key->dP, &key->p, &tmpa) !=
 104                                        PS_SUCCESS) {
 105                                psTraceCrypto("decrypt error: pstm_exptmod dP, p\n");
 106                                goto error;
 107                        }
 108                        if (pstm_exptmod(pool, &tmp, &key->dQ, &key->q, &tmpb) !=
 109                                        PS_SUCCESS) {
 110                                psTraceCrypto("decrypt error: pstm_exptmod dQ, q\n");
 111                                goto error;
 112                        }
 113                        if (pstm_sub(&tmpa, &tmpb, &tmp) != PS_SUCCESS) {
 114                                psTraceCrypto("decrypt error: sub tmpb, tmp\n");
 115                                goto error;
 116                        }
 117                        if (pstm_mulmod(pool, &tmp, &key->qP, &key->p, &tmp) != PS_SUCCESS) {
 118                                psTraceCrypto("decrypt error: pstm_mulmod qP, p\n");
 119                                goto error;
 120                        }
 121                        if (pstm_mul_comba(pool, &tmp, &key->q, &tmp, NULL, 0)
 122                                        != PS_SUCCESS){
 123                                psTraceCrypto("decrypt error: pstm_mul q \n");
 124                                goto error;
 125                        }
 126                        if (pstm_add(&tmp, &tmpb, &tmp) != PS_SUCCESS) {
 127                                psTraceCrypto("decrypt error: pstm_add tmp \n");
 128                                goto error;
 129                        }
 130                } else {
 131                        if (pstm_exptmod(pool, &tmp, &key->d, &key->N, &tmp) !=
 132                                        PS_SUCCESS) {
 133                                psTraceCrypto("psRsaCrypt error: pstm_exptmod\n");
 134                                goto error;
 135                        }
 136                }
 137        } else if (type == PUBKEY_TYPE) {
 138                if (pstm_exptmod(pool, &tmp, &key->e, &key->N, &tmp) != PS_SUCCESS) {
 139                        psTraceCrypto("psRsaCrypt error: pstm_exptmod\n");
 140                        goto error;
 141                }
 142        } else {
 143                psTraceCrypto("psRsaCrypt error: invalid type param\n");
 144                goto error;
 145        }
 146        /* Read it back */
 147        x = pstm_unsigned_bin_size(&key->N);
 148
 149        if ((uint32)x > *outlen) {
 150                res = -1;
 151                psTraceCrypto("psRsaCrypt error: pstm_unsigned_bin_size\n");
 152                goto done;
 153        }
 154        /* We want the encrypted value to always be the key size.  Pad with 0x0 */
 155        while ((uint32)x < (unsigned long)key->size) {
 156                *out++ = 0x0;
 157                x++;
 158        }
 159
 160        *outlen = x;
 161        /* Convert it */
 162        memset(out, 0x0, x);
 163
 164        if (pstm_to_unsigned_bin(pool, &tmp, out+(x-pstm_unsigned_bin_size(&tmp)))
 165                        != PS_SUCCESS) {
 166                psTraceCrypto("psRsaCrypt error: pstm_to_unsigned_bin\n");
 167                goto error;
 168        }
 169        /* Clean up and return */
 170        res = PS_SUCCESS;
 171        goto done;
 172error:
 173        res = PS_FAILURE;
 174done:
 175        if (type == PRIVKEY_TYPE && key->optimized) {
 176                //pstm_clear_multi(&tmpa, &tmpb, NULL, NULL, NULL, NULL, NULL, NULL);
 177                pstm_clear(&tmpa);
 178                pstm_clear(&tmpb);
 179        }
 180        pstm_clear(&tmp);
 181        return res;
 182}
 183
 184int32 FAST_FUNC psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
 185                                                unsigned char *in, uint32 inlen,
 186                                                unsigned char *out, uint32 outlen, void *data)
 187{
 188        int32   err;
 189        uint32  size;
 190
 191        size = key->size;
 192        if (outlen < size) {
 193//bbox          psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub\n");
 194                bb_error_msg_and_die("RSA crypt outlen:%d < size:%d", outlen, size);
 195                return PS_ARG_FAIL;
 196        }
 197
 198        if ((err = pkcs1Pad(in, inlen, out, size, PRIVKEY_TYPE, data))
 199                        < PS_SUCCESS) {
 200                psTraceCrypto("Error padding psRsaEncryptPub. Likely data too long\n");
 201                return err;
 202        }
 203        if ((err = psRsaCrypt(pool, out, size, out, (uint32*)&outlen, key,
 204                        PUBKEY_TYPE, data)) < PS_SUCCESS) {
 205                psTraceCrypto("Error performing psRsaEncryptPub\n");
 206                return err;
 207        }
 208        if (outlen != size) {
 209                psTraceCrypto("Encrypted size error in psRsaEncryptPub\n");
 210                return PS_FAILURE;
 211        }
 212        return size;
 213}
 214