blob: 60c54248ed21e33ef9dc80b99af6fbb5cf0a5119 [file] [log] [blame]
Denys Vlasenko11d00962017-01-15 00:12:42 +01001/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +01008/* 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
Denys Vlasenko6b1b0042017-01-19 15:51:00 +010011 * and (so far) almost not modified. Changes are flagged with //bbox
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +010012 */
13
Denys Vlasenko11d00962017-01-15 00:12:42 +010014#define pkcs1Pad(in, inlen, out, outlen, cryptType, userPtr) \
15 pkcs1Pad(in, inlen, out, outlen, cryptType)
Denys Vlasenko6b1b0042017-01-19 15:51:00 +010016static //bbox
Denys Vlasenko11d00962017-01-15 00:12:42 +010017int32 pkcs1Pad(unsigned char *in, uint32 inlen, unsigned char *out,
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +010018 uint32 outlen, int32 cryptType, void *userPtr)
Denys Vlasenko11d00962017-01-15 00:12:42 +010019{
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +010020 unsigned char *c;
21 int32 randomLen;
Denys Vlasenko11d00962017-01-15 00:12:42 +010022
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +010023 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 }
Denys Vlasenko11d00962017-01-15 00:12:42 +010041/*
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +010042 SECURITY: Read through the random data and change all 0x0 to 0x01.
43 This is per spec that no random bytes should be 0
Denys Vlasenko11d00962017-01-15 00:12:42 +010044*/
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +010045 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);
Denys Vlasenko11d00962017-01-15 00:12:42 +010055
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +010056 return outlen;
Denys Vlasenko11d00962017-01-15 00:12:42 +010057}
58
59#define psRsaCrypt(pool, in, inlen, out, outlen, key, type, data) \
Denys Vlasenko6b1b0042017-01-19 15:51:00 +010060 psRsaCrypt( in, inlen, out, outlen, key, type)
61static //bbox
Denys Vlasenko11d00962017-01-15 00:12:42 +010062int32 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
Denys Vlasenko6b1b0042017-01-19 15:51:00 +010070//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// }
Denys Vlasenko11d00962017-01-15 00:12:42 +010075
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 }
178 pstm_clear(&tmp);
179 return res;
180}
181
182int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +0100183 unsigned char *in, uint32 inlen,
184 unsigned char *out, uint32 outlen, void *data)
Denys Vlasenko11d00962017-01-15 00:12:42 +0100185{
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +0100186 int32 err;
187 uint32 size;
Denys Vlasenko11d00962017-01-15 00:12:42 +0100188
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +0100189 size = key->size;
190 if (outlen < size) {
Denys Vlasenko6b1b0042017-01-19 15:51:00 +0100191//bbox psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub\n");
192 bb_error_msg_and_die("RSA crypt outlen:%d < size:%d", outlen, size);
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +0100193 return PS_ARG_FAIL;
194 }
Denys Vlasenko11d00962017-01-15 00:12:42 +0100195
Denys Vlasenko3f8ecd92017-01-15 14:16:51 +0100196 if ((err = pkcs1Pad(in, inlen, out, size, PRIVKEY_TYPE, data))
197 < PS_SUCCESS) {
198 psTraceCrypto("Error padding psRsaEncryptPub. Likely data too long\n");
199 return err;
200 }
201 if ((err = psRsaCrypt(pool, out, size, out, (uint32*)&outlen, key,
202 PUBKEY_TYPE, data)) < PS_SUCCESS) {
203 psTraceCrypto("Error performing psRsaEncryptPub\n");
204 return err;
205 }
206 if (outlen != size) {
207 psTraceCrypto("Encrypted size error in psRsaEncryptPub\n");
208 return PS_FAILURE;
209 }
210 return size;
Denys Vlasenko11d00962017-01-15 00:12:42 +0100211}