Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of MiniTLS-GPL by
crypto_rsa.c
00001 /* 00002 MiniTLS - A super trimmed down TLS/SSL Library for embedded devices 00003 Author: Donatien Garnier 00004 Copyright (C) 2013-2014 AppNearMe Ltd 00005 00006 This program is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU General Public License 00008 as published by the Free Software Foundation; either version 2 00009 of the License, or (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 *//** 00020 * \file crypto_rsa.c 00021 * \copyright Copyright (c) AppNearMe Ltd 2014 00022 * \author Donatien Garnier 00023 */ 00024 00025 #define __DEBUG__ 0 00026 #ifndef __MODULE__ 00027 #define __MODULE__ "crypto_rsa.c" 00028 #endif 00029 00030 #include "core/fwk.h" 00031 #include "crypto_rsa.h" 00032 #include "inc/minitls_errors.h" 00033 #include "inc/minitls_config.h" 00034 00035 #include "crypto_math.h" 00036 #include "ltc/ltc.h" 00037 00038 static minitls_err_t crypto_pkcs_1_v1_5_encode(const uint8_t* msg, 00039 size_t msglen, 00040 size_t modulus_bitlen, 00041 crypto_prng_t* prng, 00042 uint8_t* out, 00043 size_t* outlen); 00044 static minitls_err_t crypto_rsa_exptmod(const uint8_t* in, size_t inlen, 00045 uint8_t *out, size_t* outlen, 00046 crypto_rsa_public_key_t* key); 00047 static minitls_err_t crypto_ecc_dsa_check_get_asn1_Ne(void* N, void* e, const uint8_t* key, size_t key_size); 00048 00049 minitls_err_t crypto_rsa_pkcs1_import(crypto_rsa_public_key_t* key, const uint8_t* pkcs1, size_t size) 00050 { 00051 int err; 00052 00053 /* init key */ 00054 if ((err = mp_init_multi(&key->e, &key->N, NULL)) != MINITLS_OK) { 00055 return err; 00056 } 00057 00058 if( (err = crypto_ecc_dsa_check_get_asn1_Ne(&key->N, &key->e, pkcs1, size)) != MINITLS_OK ) 00059 { 00060 goto LBL_ERR; 00061 } 00062 00063 return MINITLS_OK; 00064 LBL_ERR: 00065 mp_clear_multi(&key->e, &key->N, NULL); 00066 return err; 00067 } 00068 00069 minitls_err_t crypto_rsa_encrypt(const crypto_rsa_public_key_t* public_key, 00070 uint8_t* plaintext, size_t plaintext_size, 00071 uint8_t* secret, size_t max_secret_size, size_t* secret_size, crypto_prng_t* prng) 00072 { 00073 minitls_err_t ret; 00074 00075 /* get modulus len in bits */ 00076 size_t modulus_bitlen = mp_count_bits( (&public_key->N)); 00077 00078 /* outlen must be at least the size of the modulus */ 00079 size_t modulus_bytelen = mp_unsigned_bin_size( (&public_key->N)); 00080 if (modulus_bytelen > max_secret_size) { 00081 WARN("modulus_bytelen = %d but max_secret_size = %d", modulus_bytelen, max_secret_size); 00082 *secret_size = modulus_bytelen; 00083 return MINITLS_ERR_BUFFER_TOO_SMALL; 00084 } 00085 00086 //Apply padding 00087 *secret_size = max_secret_size; 00088 ret = crypto_pkcs_1_v1_5_encode(plaintext, plaintext_size, modulus_bitlen, prng, secret, secret_size); 00089 if(ret) 00090 { 00091 return ret; 00092 } 00093 00094 //Do the exponentiation 00095 ret = crypto_rsa_exptmod(secret, *secret_size, secret, secret_size, public_key); 00096 if(ret) 00097 { 00098 return ret; 00099 } 00100 00101 return MINITLS_OK; 00102 } 00103 00104 minitls_err_t crypto_rsa_exptmod(const uint8_t* in, size_t inlen, 00105 uint8_t *out, size_t* outlen, 00106 crypto_rsa_public_key_t* key) 00107 { 00108 fp_int tmp; 00109 unsigned long x; 00110 int err; 00111 00112 /* init and copy into tmp */ 00113 if ((err = mp_init_multi(&tmp, NULL)) != MINITLS_OK) { return err; } 00114 mp_read_unsigned_bin(&tmp, (unsigned char *)in, (int)inlen); 00115 00116 /* sanity check on the input */ 00117 if (mp_cmp(&key->N, &tmp) == MP_LT) { 00118 err = MINITLS_ERR_WRONG_LENGTH; 00119 goto error; 00120 } 00121 00122 /* exptmod it */ 00123 if ((err = mp_exptmod(&tmp, &key->e, &key->N, &tmp)) != MINITLS_OK) { goto error; } 00124 00125 /* read it back */ 00126 x = (unsigned long)mp_unsigned_bin_size(&key->N); 00127 if (x > *outlen) { 00128 *outlen = x; 00129 err = MINITLS_ERR_BUFFER_TOO_SMALL; 00130 goto error; 00131 } 00132 00133 /* this should never happen ... */ 00134 if (mp_unsigned_bin_size(&tmp) > mp_unsigned_bin_size(&key->N)) { 00135 err = MINITLS_ERR_CRYPTO; 00136 goto error; 00137 } 00138 *outlen = x; 00139 00140 /* convert it */ 00141 zeromem(out, x); 00142 mp_to_unsigned_bin(&tmp, out+(x-mp_unsigned_bin_size(&tmp))); 00143 00144 /* clean up and return */ 00145 err = MINITLS_OK; 00146 error: 00147 mp_clear_multi(&tmp, NULL); 00148 return err; 00149 } 00150 00151 minitls_err_t crypto_pkcs_1_v1_5_encode(const uint8_t* msg, 00152 size_t msglen, 00153 size_t modulus_bitlen, 00154 crypto_prng_t* prng, 00155 uint8_t* out, 00156 size_t* outlen) 00157 { 00158 unsigned long modulus_len, ps_len, i; 00159 unsigned char *ps; 00160 int result; 00161 00162 modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); 00163 00164 /* test message size */ 00165 if ((msglen + 11) > modulus_len) { 00166 return MINITLS_ERR_WRONG_LENGTH; 00167 } 00168 00169 if (*outlen < modulus_len) { 00170 *outlen = modulus_len; 00171 result = MINITLS_ERR_BUFFER_TOO_SMALL; 00172 goto bail; 00173 } 00174 00175 /* generate an octets string PS */ 00176 ps = &out[2]; 00177 ps_len = modulus_len - msglen - 3; 00178 00179 00180 /* now choose a random ps */ 00181 crypto_prng_get(prng, ps, ps_len); 00182 00183 /* transform zero bytes (if any) to non-zero random bytes */ 00184 for (i = 0; i < ps_len; i++) { 00185 while (ps[i] == 0) { 00186 crypto_prng_get(prng, &ps[i], 1); 00187 } 00188 } 00189 00190 /* create string of length modulus_len */ 00191 out[0] = 0x00; 00192 out[1] = 2; /* block_type is Block type 2 (LTC_PKCS #1 v1.5 encryption padding) */ 00193 out[2 + ps_len] = 0x00; 00194 memcpy(&out[2 + ps_len + 1], msg, msglen); 00195 *outlen = modulus_len; 00196 00197 result = MINITLS_OK; 00198 bail: 00199 return result; 00200 } 00201 00202 00203 //Decode (&N,&e) integers from ASN.1-encoded public key 00204 #define ENSURE_SIZE(actual_size, min_size) do{ if( (actual_size) < (min_size) ) { return MINITLS_ERR_PARAMETERS; } }while(0) 00205 minitls_err_t crypto_ecc_dsa_check_get_asn1_Ne(void* N, void* e, const uint8_t* key, size_t key_size) 00206 { 00207 const uint8_t* p = key; 00208 size_t sz = key_size; 00209 00210 /* OpenSSL encoded keys have this format: 00211 * 00212 * SEQUENCE(2 elem) 00213 * * SEQUENCE(2 elem) 00214 * * * OBJECT IDENTIFIER1.2.840.113549.1.1.1 00215 * * * NULL 00216 * * BIT STRING(1 elem) 00217 * * * SEQUENCE(2 elem) 00218 * * * * INTEGER(1024 bit) 00219 * * * * INTEGER 65537 00220 * 00221 * 00222 */ 00223 00224 00225 00226 00227 ENSURE_SIZE(sz, 1); 00228 00229 if( (p[0] != 0x30) && (p[0] != 0x31) ) //Sequence, SET types 00230 { 00231 return MINITLS_ERR_PARAMETERS; 00232 } 00233 00234 p++; 00235 sz--; 00236 00237 ENSURE_SIZE(sz, 1); 00238 00239 size_t seq_size; 00240 //Get sequence length 00241 if(*p < 0x80) 00242 { 00243 seq_size = p[0]; 00244 p++; 00245 sz--; 00246 } 00247 else if(*p == 0x81) 00248 { 00249 ENSURE_SIZE(sz, 2); 00250 seq_size = p[1]; 00251 p+=2; 00252 sz-=2; 00253 } 00254 else if(*p == 0x82) 00255 { 00256 ENSURE_SIZE(sz, 3); 00257 seq_size = (p[1] << 8) | p[2]; 00258 p+=3; 00259 sz-=3; 00260 } 00261 else if(*p == 0x83) 00262 { 00263 ENSURE_SIZE(sz, 4); 00264 seq_size = (p[1] << 16) | (p[2] << 8) | p[3]; 00265 p+=4; 00266 sz-=4; 00267 } 00268 else if(*p == 0x84) 00269 { 00270 ENSURE_SIZE(sz, 5); 00271 seq_size = (p[1] << 24) |(p[2] << 16) | (p[3] << 8) | p[4]; 00272 p+=5; 00273 sz-=5; 00274 } 00275 else 00276 { 00277 return MINITLS_ERR_PARAMETERS; 00278 } 00279 00280 //Check that sequence size == remaining bytes size 00281 if( seq_size != sz ) 00282 { 00283 return MINITLS_ERR_PARAMETERS; 00284 } 00285 00286 //Read integers 00287 for(int i = 0; i < 2; i++) 00288 { 00289 ENSURE_SIZE(sz, 1); 00290 00291 if( p[0] != 2 ) //Integer type 00292 { 00293 return MINITLS_ERR_PARAMETERS; 00294 } 00295 00296 p++; 00297 sz--; 00298 00299 ENSURE_SIZE(sz, 1); 00300 00301 size_t integer_size; 00302 //Get sequence length 00303 if(*p < 0x80) 00304 { 00305 integer_size = p[0]; 00306 p++; 00307 sz--; 00308 } 00309 else if(*p == 0x81) 00310 { 00311 ENSURE_SIZE(sz, 2); 00312 integer_size = p[1]; 00313 p+=2; 00314 sz-=2; 00315 } 00316 else if(*p == 0x82) 00317 { 00318 ENSURE_SIZE(sz, 3); 00319 integer_size = (p[1] << 8) | p[2]; 00320 p+=3; 00321 sz-=3; 00322 } 00323 else if(*p == 0x83) 00324 { 00325 ENSURE_SIZE(sz, 4); 00326 integer_size = (p[1] << 16) | (p[2] << 8) | p[3]; 00327 p+=4; 00328 sz-=4; 00329 } 00330 else if(*p == 0x84) 00331 { 00332 ENSURE_SIZE(sz, 5); 00333 integer_size = (p[1] << 24) |(p[2] << 16) | (p[3] << 8) | p[4]; 00334 p+=5; 00335 sz-=5; 00336 } 00337 else 00338 { 00339 return MINITLS_ERR_PARAMETERS; 00340 } 00341 00342 //Check that we have enough bytes remaining 00343 ENSURE_SIZE(sz, integer_size); 00344 00345 DBG("Integer of size %d", integer_size); 00346 00347 //Read integer 00348 void* integer = (i==0)?N:e; 00349 00350 /*int err;*/ 00351 /*if ((err = */mp_read_unsigned_bin(integer, (unsigned char *)p, integer_size);/*) != MINITLS_OK) { 00352 return err; 00353 }*/ 00354 00355 p+=integer_size; 00356 sz-=integer_size; 00357 } 00358 00359 if(sz > 0) 00360 { 00361 //Unread parameters left in sequence 00362 return MINITLS_ERR_PARAMETERS; 00363 } 00364 00365 return MINITLS_OK; 00366 } 00367
Generated on Tue Jul 12 2022 19:20:10 by
1.7.2
