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.
Dependents: MiniTLS-HTTPS-Example
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 Wed Jul 13 2022 00:22:54 by
1.7.2