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.
rsa.c
00001 /** 00002 * @file rsa.c 00003 * @brief RSA public-key cryptography standard 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneCrypto Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @section Description 00026 * 00027 * RSA is an algorithm for public-key cryptography which is suitable for signing 00028 * as well as encryption. Refer to PKCS #1 (RSA Cryptography Standard) 00029 * 00030 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00031 * @version 1.7.6 00032 **/ 00033 00034 //Switch to the appropriate trace level 00035 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL 00036 00037 //Dependencies 00038 #include <stdlib.h> 00039 #include <string.h> 00040 #include "crypto.h" 00041 #include "rsa.h" 00042 #include "mpi.h" 00043 #include "asn1.h" 00044 #include "oid.h" 00045 #include "debug.h" 00046 00047 //Check crypto library configuration 00048 #if (RSA_SUPPORT == ENABLED) 00049 00050 //PKCS #1 OID (1.2.840.113549.1.1) 00051 const uint8_t PKCS1_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01}; 00052 //RSA encryption OID (1.2.840.113549.1.1.1) 00053 const uint8_t RSA_ENCRYPTION_OID[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01}; 00054 //MD5 with RSA encryption OID (1.2.840.113549.1.1.4) 00055 const uint8_t MD5_WITH_RSA_ENCRYPTION_OID[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04}; 00056 //SHA-1 with RSA encryption OID (1.2.840.113549.1.1.5) 00057 const uint8_t SHA1_WITH_RSA_ENCRYPTION_OID[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05}; 00058 //SHA-256 with RSA encryption OID (1.2.840.113549.1.1.11) 00059 const uint8_t SHA256_WITH_RSA_ENCRYPTION_OID[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B}; 00060 //SHA-384 with RSA encryption OID (1.2.840.113549.1.1.12) 00061 const uint8_t SHA384_WITH_RSA_ENCRYPTION_OID[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0C}; 00062 //SHA-512 with RSA encryption OID (1.2.840.113549.1.1.13) 00063 const uint8_t SHA512_WITH_RSA_ENCRYPTION_OID[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0D}; 00064 //RSA PKCS #1 v1.5 signature with SHA-3-224 OID (2.16.840.1.101.3.4.3.13) 00065 const uint8_t RSASSA_PKCS1_v1_5_WITH_SHA3_224_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0D}; 00066 //RSA PKCS #1 v1.5 signature with SHA-3-256 OID (2.16.840.1.101.3.4.3.14) 00067 const uint8_t RSASSA_PKCS1_v1_5_WITH_SHA3_256_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0E}; 00068 //RSA PKCS #1 v1.5 signature with SHA-3-384 OID (2.16.840.1.101.3.4.3.15) 00069 const uint8_t RSASSA_PKCS1_v1_5_WITH_SHA3_384_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0F}; 00070 //RSA PKCS #1 v1.5 signature with SHA-3-512 OID (2.16.840.1.101.3.4.3.16) 00071 const uint8_t RSASSA_PKCS1_v1_5_WITH_SHA3_512_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x10}; 00072 00073 00074 /** 00075 * @brief Initialize a RSA public key 00076 * @param[in] key Pointer to the RSA public key to initialize 00077 **/ 00078 00079 void rsaInitPublicKey(RsaPublicKey *key) 00080 { 00081 //Initialize multiple precision integers 00082 mpiInit(&key->n); 00083 mpiInit(&key->e); 00084 } 00085 00086 00087 /** 00088 * @brief Release a RSA public key 00089 * @param[in] key Pointer to the RSA public key to free 00090 **/ 00091 00092 void rsaFreePublicKey(RsaPublicKey *key) 00093 { 00094 //Free multiple precision integers 00095 mpiFree(&key->n); 00096 mpiFree(&key->e); 00097 } 00098 00099 00100 /** 00101 * @brief Initialize a RSA private key 00102 * @param[in] key Pointer to the RSA private key to initialize 00103 **/ 00104 00105 void rsaInitPrivateKey(RsaPrivateKey *key) 00106 { 00107 //Initialize multiple precision integers 00108 mpiInit(&key->n); 00109 mpiInit(&key->e); 00110 mpiInit(&key->d); 00111 mpiInit(&key->p); 00112 mpiInit(&key->q); 00113 mpiInit(&key->dp); 00114 mpiInit(&key->dq); 00115 mpiInit(&key->qinv); 00116 } 00117 00118 00119 /** 00120 * @brief Release a RSA private key 00121 * @param[in] key Pointer to the RSA private key to free 00122 **/ 00123 00124 void rsaFreePrivateKey(RsaPrivateKey *key) 00125 { 00126 //Free multiple precision integers 00127 mpiFree(&key->n); 00128 mpiFree(&key->e); 00129 mpiFree(&key->d); 00130 mpiFree(&key->p); 00131 mpiFree(&key->q); 00132 mpiFree(&key->dp); 00133 mpiFree(&key->dq); 00134 mpiFree(&key->qinv); 00135 } 00136 00137 00138 /** 00139 * @brief RSA encryption primitive 00140 * 00141 * The RSA encryption primitive produces a ciphertext representative from 00142 * a message representative under the control of a public key 00143 * 00144 * @param[in] key RSA public key 00145 * @param[in] m Message representative 00146 * @param[out] c Ciphertext representative 00147 * @return Error code 00148 **/ 00149 00150 error_t rsaep(const RsaPublicKey *key, const Mpi *m, Mpi *c) 00151 { 00152 //Ensure the RSA public key is valid 00153 if(!key->n.size || !key->e.size) 00154 return ERROR_INVALID_PARAMETER; 00155 00156 //The message representative m shall be between 0 and n - 1 00157 if(mpiCompInt(m, 0) < 0 || mpiComp(m, &key->n) >= 0) 00158 return ERROR_OUT_OF_RANGE; 00159 00160 //Perform modular exponentiation (c = m ^ e mod n) 00161 return mpiExpMod(c, m, &key->e, &key->n); 00162 } 00163 00164 00165 /** 00166 * @brief RSA decryption primitive 00167 * 00168 * The RSA decryption primitive recovers the message representative from 00169 * the ciphertext representative under the control of a private key 00170 * 00171 * @param[in] key RSA private key 00172 * @param[in] c Ciphertext representative 00173 * @param[out] m Message representative 00174 * @return Error code 00175 **/ 00176 00177 error_t rsadp(const RsaPrivateKey *key, const Mpi *c, Mpi *m) 00178 { 00179 error_t error; 00180 Mpi m1; 00181 Mpi m2; 00182 Mpi h; 00183 00184 //The ciphertext representative c shall be between 0 and n - 1 00185 if(mpiCompInt(c, 0) < 0 || mpiComp(c, &key->n) >= 0) 00186 return ERROR_OUT_OF_RANGE; 00187 00188 //Initialize multiple-precision integers 00189 mpiInit(&m1); 00190 mpiInit(&m2); 00191 mpiInit(&h); 00192 00193 //Use the Chinese remainder algorithm? 00194 if(key->n.size && key->p.size && key->q.size && 00195 key->dp.size && key->dq.size && key->qinv.size) 00196 { 00197 //Compute m1 = c ^ dP mod p 00198 MPI_CHECK(mpiExpMod(&m1, c, &key->dp, &key->p)); 00199 //Compute m2 = c ^ dQ mod q 00200 MPI_CHECK(mpiExpMod(&m2, c, &key->dq, &key->q)); 00201 //Let h = (m1 - m2) * qInv mod p 00202 MPI_CHECK(mpiSub(&h, &m1, &m2)); 00203 MPI_CHECK(mpiMulMod(&h, &h, &key->qinv, &key->p)); 00204 //Let m = m2 + q * h 00205 MPI_CHECK(mpiMul(m, &key->q, &h)); 00206 MPI_CHECK(mpiAdd(m, m, &m2)); 00207 } 00208 //Use modular exponentiation? 00209 else if(key->n.size && key->d.size) 00210 { 00211 //Let m = c ^ d mod n 00212 error = mpiExpMod(m, c, &key->d, &key->n); 00213 } 00214 //Invalid parameters? 00215 else 00216 { 00217 //Report an error 00218 error = ERROR_INVALID_PARAMETER; 00219 } 00220 00221 end: 00222 //Free previously allocated memory 00223 mpiFree(&m1); 00224 mpiFree(&m2); 00225 mpiFree(&h); 00226 00227 //Return status code 00228 return error; 00229 } 00230 00231 00232 /** 00233 * @brief RSA signature primitive 00234 * 00235 * The RSA signature primitive produces a signature representative from 00236 * a message representative under the control of a private key 00237 * 00238 * @param[in] key RSA private key 00239 * @param[in] m Message representative 00240 * @param[out] s Signature representative 00241 * @return Error code 00242 **/ 00243 00244 error_t rsasp1(const RsaPrivateKey *key, const Mpi *m, Mpi *s) 00245 { 00246 //RSASP1 primitive is the same as RSADP except for the names of its 00247 //input and output arguments. They are distinguished as they are 00248 //intended for different purposes 00249 return rsadp(key, m, s); 00250 } 00251 00252 00253 /** 00254 * @brief RSA verification primitive 00255 * 00256 * The RSA verification primitive recovers the message representative from 00257 * the signature representative under the control of a public key 00258 * 00259 * @param[in] key RSA public key 00260 * @param[in] s Signature representative 00261 * @param[out] m Message representative 00262 * @return Error code 00263 **/ 00264 00265 error_t rsavp1(const RsaPublicKey *key, const Mpi *s, Mpi *m) 00266 { 00267 //RSAVP1 primitive is the same as RSAEP except for the names of its 00268 //input and output arguments. They are distinguished as they are 00269 //intended for different purposes 00270 return rsaep(key, s, m); 00271 } 00272 00273 00274 /** 00275 * @brief PKCS #1 v1.5 encryption operation 00276 * @param[in] prngAlgo PRNG algorithm 00277 * @param[in] prngContext Pointer to the PRNG context 00278 * @param[in] key Recipient's RSA public key 00279 * @param[in] message Message to be encrypted 00280 * @param[in] messageLength Length of the message to be encrypted 00281 * @param[out] ciphertext Ciphertext resulting from the encryption operation 00282 * @param[out] ciphertextLength Length of the resulting ciphertext 00283 * @return Error code 00284 **/ 00285 00286 error_t rsaesPkcs1v15Encrypt(const PrngAlgo *prngAlgo, void *prngContext, const RsaPublicKey *key, 00287 const uint8_t *message, size_t messageLength, uint8_t *ciphertext, size_t *ciphertextLength) 00288 { 00289 error_t error; 00290 uint_t i; 00291 uint_t j; 00292 uint_t k; 00293 uint_t n; 00294 uint8_t *p; 00295 Mpi m; 00296 Mpi c; 00297 00298 //Check parameters 00299 if(key == NULL || message == NULL) 00300 return ERROR_INVALID_PARAMETER; 00301 if(ciphertext == NULL || ciphertextLength == NULL) 00302 return ERROR_INVALID_PARAMETER; 00303 00304 //Debug message 00305 TRACE_DEBUG("RSA PKCS #1 v1.5 encryption...\r\n"); 00306 TRACE_DEBUG(" Modulus:\r\n"); 00307 TRACE_DEBUG_MPI(" ", &key->n); 00308 TRACE_DEBUG(" Public exponent:\r\n"); 00309 TRACE_DEBUG_MPI(" ", &key->e); 00310 TRACE_DEBUG(" Message:\r\n"); 00311 TRACE_DEBUG_ARRAY(" ", message, messageLength); 00312 00313 //Initialize multiple-precision integers 00314 mpiInit(&m); 00315 mpiInit(&c); 00316 00317 //Get the length in octets of the modulus n 00318 k = mpiGetByteLength(&key->n); 00319 00320 //Check the length of the message 00321 if((messageLength + 11) > k) 00322 return ERROR_INVALID_LENGTH; 00323 00324 //Point to the buffer where the encoded message EM will be formatted 00325 p = ciphertext; 00326 00327 //The leading 0x00 octet ensures that the encoded message, 00328 //converted to an integer, is less than the modulus 00329 *(p++) = 0x00; 00330 //For a public-key operation, the block type BT shall be 0x02 00331 *(p++) = 0x02; 00332 00333 //Length of the padding string PS 00334 n = k - messageLength - 3; 00335 00336 //Generate the padding string (pseudo-randomly generated non-zero octets) 00337 while(n > 0) 00338 { 00339 //Generate random data 00340 error = prngAlgo->read(prngContext, p, n); 00341 //Any error to report? 00342 if(error) 00343 return error; 00344 00345 //Parse the resulting octet string 00346 for(i = 0, j = 0; j < n; j++) 00347 { 00348 //Strip any byte with a value of zero 00349 if(p[j] != 0) 00350 p[i++] = p[j]; 00351 } 00352 00353 //Advance data pointer 00354 p += i; 00355 n -= i; 00356 } 00357 00358 //Append a 0x00 octet to the padding string 00359 *(p++) = 0x00; 00360 //Copy the message to be encrypted 00361 memcpy(p, message, messageLength); 00362 00363 //Rewind to the beginning of the encoded message 00364 p = ciphertext; 00365 00366 //Debug message 00367 TRACE_DEBUG(" Encoded message\r\n"); 00368 TRACE_DEBUG_ARRAY(" ", p, k); 00369 00370 //Start of exception handling block 00371 do 00372 { 00373 //Convert the encoded message EM to an integer message representative m 00374 error = mpiReadRaw(&m, p, k); 00375 //Conversion failed? 00376 if(error) 00377 break; 00378 00379 //Apply the RSAEP encryption primitive 00380 error = rsaep(key, &m, &c); 00381 //Any error to report? 00382 if(error) 00383 break; 00384 00385 //Convert the ciphertext representative c to a ciphertext of length k octets 00386 error = mpiWriteRaw(&c, ciphertext, k); 00387 //Conversion failed? 00388 if(error) 00389 break; 00390 00391 //Length of the resulting ciphertext 00392 *ciphertextLength = k; 00393 00394 //Debug message 00395 TRACE_DEBUG(" Ciphertext:\r\n"); 00396 TRACE_DEBUG_ARRAY(" ", ciphertext, *ciphertextLength); 00397 00398 //End of exception handling block 00399 } while(0); 00400 00401 //Free previously allocated memory 00402 mpiFree(&m); 00403 mpiFree(&c); 00404 00405 //Return status code 00406 return error; 00407 } 00408 00409 00410 /** 00411 * @brief PKCS #1 v1.5 decryption operation 00412 * @param[in] key Recipient's RSA private key 00413 * @param[in] ciphertext Ciphertext to be decrypted 00414 * @param[in] ciphertextLength Length of the ciphertext to be decrypted 00415 * @param[out] message Output buffer where to store the decrypted message 00416 * @param[in] messageSize Size of the output buffer 00417 * @param[out] messageLength Length of the decrypted message 00418 * @return Error code 00419 **/ 00420 00421 error_t rsaesPkcs1v15Decrypt(const RsaPrivateKey *key, const uint8_t *ciphertext, 00422 size_t ciphertextLength, uint8_t *message, size_t messageSize, size_t *messageLength) 00423 { 00424 error_t error; 00425 uint_t i; 00426 uint_t k; 00427 uint8_t *em; 00428 Mpi c; 00429 Mpi m; 00430 00431 //Check parameters 00432 if(key == NULL || ciphertext == NULL) 00433 return ERROR_INVALID_PARAMETER; 00434 if(message == NULL || messageLength == NULL) 00435 return ERROR_INVALID_PARAMETER; 00436 00437 //Debug message 00438 TRACE_DEBUG("RSA PKCS #1 v1.5 decryption...\r\n"); 00439 TRACE_DEBUG(" Modulus:\r\n"); 00440 TRACE_DEBUG_MPI(" ", &key->n); 00441 TRACE_DEBUG(" Public exponent:\r\n"); 00442 TRACE_DEBUG_MPI(" ", &key->e); 00443 TRACE_DEBUG(" Private exponent:\r\n"); 00444 TRACE_DEBUG_MPI(" ", &key->d); 00445 TRACE_DEBUG(" Prime 1:\r\n"); 00446 TRACE_DEBUG_MPI(" ", &key->p); 00447 TRACE_DEBUG(" Prime 2:\r\n"); 00448 TRACE_DEBUG_MPI(" ", &key->q); 00449 TRACE_DEBUG(" Prime exponent 1:\r\n"); 00450 TRACE_DEBUG_MPI(" ", &key->dp); 00451 TRACE_DEBUG(" Prime exponent 2:\r\n"); 00452 TRACE_DEBUG_MPI(" ", &key->dq); 00453 TRACE_DEBUG(" Coefficient:\r\n"); 00454 TRACE_DEBUG_MPI(" ", &key->qinv); 00455 TRACE_DEBUG(" Ciphertext:\r\n"); 00456 TRACE_DEBUG_ARRAY(" ", ciphertext, ciphertextLength); 00457 00458 //Initialize multiple-precision integers 00459 mpiInit(&c); 00460 mpiInit(&m); 00461 00462 //Get the length in octets of the modulus n 00463 k = mpiGetByteLength(&key->n); 00464 00465 //Check the length of the ciphertext 00466 if(ciphertextLength != k || ciphertextLength < 11) 00467 return ERROR_INVALID_LENGTH; 00468 00469 //Allocate a buffer to store the encoded message EM 00470 em = cryptoAllocMem(k); 00471 //Failed to allocate memory? 00472 if(em == NULL) 00473 return ERROR_OUT_OF_MEMORY; 00474 00475 //Start of exception handling block 00476 do 00477 { 00478 //Convert the ciphertext to an integer ciphertext representative c 00479 error = mpiReadRaw(&c, ciphertext, ciphertextLength); 00480 //Conversion failed? 00481 if(error) 00482 break; 00483 00484 //Apply the RSADP decryption primitive 00485 error = rsadp(key, &c, &m); 00486 //Any error to report? 00487 if(error) 00488 break; 00489 00490 //Convert the message representative m to an encoded message EM of length k octets 00491 error = mpiWriteRaw(&m, em, k); 00492 //Conversion failed? 00493 if(error) 00494 break; 00495 00496 //Debug message 00497 TRACE_DEBUG(" Encoded message\r\n"); 00498 TRACE_DEBUG_ARRAY(" ", em, k); 00499 00500 //The first octet of EM must have a value of 0x00 00501 //and the block type BT shall be 0x02 00502 if(em[0] != 0x00 || em[1] != 0x02) 00503 { 00504 //Report an error 00505 error = ERROR_UNEXPECTED_VALUE; 00506 break; 00507 } 00508 00509 //An octet with hexadecimal value 0x00 is used to separate PS from M 00510 for(i = 2; i < k && em[i] != 0x00; i++); 00511 00512 //Check whether the padding string is valid 00513 if(i < 10 || i >= k) 00514 { 00515 //Report an error 00516 error = ERROR_INVALID_PADDING; 00517 break; 00518 } 00519 00520 //Ensure that the output buffer is large enough 00521 if(messageSize < (k - i - 1)) 00522 { 00523 //Report an error 00524 error = ERROR_INVALID_LENGTH; 00525 break; 00526 } 00527 00528 //Recover the length of the message 00529 *messageLength = k - i - 1; 00530 //Copy the message contents 00531 memcpy(message, em + i + 1, *messageLength); 00532 00533 //Debug message 00534 TRACE_DEBUG(" Message:\r\n"); 00535 TRACE_DEBUG_ARRAY(" ", message, *messageLength); 00536 00537 //End of exception handling block 00538 } while(0); 00539 00540 //Release multiple precision integers 00541 mpiFree(&c); 00542 mpiFree(&m); 00543 //Free previously allocated memory 00544 cryptoFreeMem(em); 00545 00546 //Return status code 00547 return error; 00548 } 00549 00550 00551 /** 00552 * @brief PKCS #1 v1.5 signature generation operation 00553 * @param[in] key Signer's RSA private key 00554 * @param[in] hash Hash function used to digest the message 00555 * @param[in] digest Digest of the message to be signed 00556 * @param[out] signature Resulting signature 00557 * @param[out] signatureLength Length of the resulting signature 00558 * @return Error code 00559 **/ 00560 00561 error_t rsassaPkcs1v15Sign(const RsaPrivateKey *key, const HashAlgo *hash, 00562 const uint8_t *digest, uint8_t *signature, size_t *signatureLength) 00563 { 00564 error_t error; 00565 uint_t k; 00566 uint8_t *em; 00567 Mpi m; 00568 Mpi s; 00569 00570 //Check parameters 00571 if(key == NULL || hash == NULL || digest == NULL) 00572 return ERROR_INVALID_PARAMETER; 00573 if(signature == NULL || signatureLength == NULL) 00574 return ERROR_INVALID_PARAMETER; 00575 00576 //Debug message 00577 TRACE_DEBUG("RSA PKCS #1 v1.5 signature generation...\r\n"); 00578 TRACE_DEBUG(" Modulus:\r\n"); 00579 TRACE_DEBUG_MPI(" ", &key->n); 00580 TRACE_DEBUG(" Public exponent:\r\n"); 00581 TRACE_DEBUG_MPI(" ", &key->e); 00582 TRACE_DEBUG(" Private exponent:\r\n"); 00583 TRACE_DEBUG_MPI(" ", &key->d); 00584 TRACE_DEBUG(" Prime 1:\r\n"); 00585 TRACE_DEBUG_MPI(" ", &key->p); 00586 TRACE_DEBUG(" Prime 2:\r\n"); 00587 TRACE_DEBUG_MPI(" ", &key->q); 00588 TRACE_DEBUG(" Prime exponent 1:\r\n"); 00589 TRACE_DEBUG_MPI(" ", &key->dp); 00590 TRACE_DEBUG(" Prime exponent 2:\r\n"); 00591 TRACE_DEBUG_MPI(" ", &key->dq); 00592 TRACE_DEBUG(" Coefficient:\r\n"); 00593 TRACE_DEBUG_MPI(" ", &key->qinv); 00594 TRACE_DEBUG(" Message digest:\r\n"); 00595 TRACE_DEBUG_ARRAY(" ", digest, hash->digestSize); 00596 00597 //Initialize multiple-precision integers 00598 mpiInit(&m); 00599 mpiInit(&s); 00600 00601 //Get the length in octets of the modulus n 00602 k = mpiGetByteLength(&key->n); 00603 //Point to the buffer where the encoded message EM will be generated 00604 em = signature; 00605 00606 //Apply the EMSA-PKCS1-v1.5 encoding operation 00607 error = emsaPkcs1v15Encode(hash, digest, em, k); 00608 //Any error to report? 00609 if(error) 00610 return error; 00611 00612 //Debug message 00613 TRACE_DEBUG(" Encoded message\r\n"); 00614 TRACE_DEBUG_ARRAY(" ", em, k); 00615 00616 //Start of exception handling block 00617 do 00618 { 00619 //Convert the encoded message EM to an integer message representative m 00620 error = mpiReadRaw(&m, em, k); 00621 //Conversion failed? 00622 if(error) 00623 break; 00624 00625 //Apply the RSASP1 signature primitive 00626 error = rsasp1(key, &m, &s); 00627 //Any error to report? 00628 if(error) 00629 break; 00630 00631 //Convert the signature representative s to a signature of length k octets 00632 error = mpiWriteRaw(&s, signature, k); 00633 //Conversion failed? 00634 if(error) 00635 break; 00636 00637 //Length of the resulting signature 00638 *signatureLength = k; 00639 00640 //Debug message 00641 TRACE_DEBUG(" Signature:\r\n"); 00642 TRACE_DEBUG_ARRAY(" ", signature, *signatureLength); 00643 00644 //End of exception handling block 00645 } while(0); 00646 00647 //Free previously allocated memory 00648 mpiFree(&m); 00649 mpiFree(&s); 00650 00651 //Return status code 00652 return error; 00653 } 00654 00655 00656 /** 00657 * @brief PKCS #1 v1.5 signature verification operation 00658 * @param[in] key Signer's RSA public key 00659 * @param[in] hash Hash function used to digest the message 00660 * @param[in] digest Digest of the message whose signature is to be verified 00661 * @param[in] signature Signature to be verified 00662 * @param[in] signatureLength Length of the signature to be verified 00663 * @return Error code 00664 **/ 00665 00666 error_t rsassaPkcs1v15Verify(const RsaPublicKey *key, const HashAlgo *hash, 00667 const uint8_t *digest, const uint8_t *signature, size_t signatureLength) 00668 { 00669 error_t error; 00670 uint_t k; 00671 uint8_t *em; 00672 const uint8_t *oid; 00673 size_t oidLength; 00674 const uint8_t *d; 00675 size_t dLength; 00676 Mpi s; 00677 Mpi m; 00678 00679 //Check parameters 00680 if(key == NULL || hash == NULL || digest == NULL || signature == NULL) 00681 return ERROR_INVALID_PARAMETER; 00682 00683 //Debug message 00684 TRACE_DEBUG("RSA PKCS #1 v1.5 signature verification...\r\n"); 00685 TRACE_DEBUG(" Modulus:\r\n"); 00686 TRACE_DEBUG_MPI(" ", &key->n); 00687 TRACE_DEBUG(" Public exponent:\r\n"); 00688 TRACE_DEBUG_MPI(" ", &key->e); 00689 TRACE_DEBUG(" Message digest:\r\n"); 00690 TRACE_DEBUG_ARRAY(" ", digest, hash->digestSize); 00691 TRACE_DEBUG(" Signature:\r\n"); 00692 TRACE_DEBUG_ARRAY(" ", signature, signatureLength); 00693 00694 //Initialize multiple-precision integers 00695 mpiInit(&s); 00696 mpiInit(&m); 00697 00698 //Get the length in octets of the modulus n 00699 k = mpiGetByteLength(&key->n); 00700 00701 //Check the length of the signature 00702 if(signatureLength != k) 00703 return ERROR_INVALID_LENGTH; 00704 00705 //Allocate a memory buffer to hold the encoded message 00706 em = cryptoAllocMem(k); 00707 //Failed to allocate memory? 00708 if(em == NULL) 00709 return ERROR_OUT_OF_MEMORY; 00710 00711 //Start of exception handling block 00712 do 00713 { 00714 //Convert the signature to an integer signature representative s 00715 error = mpiReadRaw(&s, signature, signatureLength); 00716 //Conversion failed? 00717 if(error) 00718 break; 00719 00720 //Apply the RSAVP1 verification primitive 00721 error = rsavp1(key, &s, &m); 00722 //Any error to report? 00723 if(error) 00724 break; 00725 00726 //Convert the message representative m to an encoded message EM of length k octets 00727 error = mpiWriteRaw(&m, em, k); 00728 //Conversion failed? 00729 if(error) 00730 break; 00731 00732 //Debug message 00733 TRACE_DEBUG(" Encoded message\r\n"); 00734 TRACE_DEBUG_ARRAY(" ", em, k); 00735 00736 //Parse the encoded message EM 00737 error = emsaPkcs1v15Decode(em, k, &oid, &oidLength, &d, &dLength); 00738 //Any error to report? 00739 if(error) 00740 break; 00741 00742 //Assume an error... 00743 error = ERROR_INVALID_SIGNATURE_ALGO; 00744 //Ensure the hash algorithm identifier matches the OID 00745 if(oidComp(oid, oidLength, hash->oid, hash->oidSize)) 00746 break; 00747 //Check the length of the digest 00748 if(dLength != hash->digestSize) 00749 break; 00750 00751 //Compare the message digest 00752 error = memcmp(digest, d, dLength) ? ERROR_INVALID_SIGNATURE : NO_ERROR; 00753 00754 //End of exception handling block 00755 } while(0); 00756 00757 //Release multiple precision integers 00758 mpiFree(&s); 00759 mpiFree(&m); 00760 //Free previously allocated memory 00761 cryptoFreeMem(em); 00762 00763 //Return status code 00764 return error; 00765 } 00766 00767 00768 /** 00769 * @brief PKCS #1 v1.5 encoding method 00770 * @param[in] hash Hash function used to digest the message 00771 * @param[in] digest Digest of the message to be signed 00772 * @param[out] em Encoded message 00773 * @param[in] emLength Intended length of the encoded message 00774 * @return Error code 00775 **/ 00776 00777 error_t emsaPkcs1v15Encode(const HashAlgo *hash, 00778 const uint8_t *digest, uint8_t *em, size_t emLength) 00779 { 00780 uint_t i; 00781 size_t paddingLength; 00782 00783 //Ensure the length of the digest is valid 00784 if((hash->oidSize + hash->digestSize + 21) > emLength) 00785 return ERROR_INVALID_LENGTH; 00786 00787 //The leading 0x00 octet ensures that the encoded message, 00788 //converted to an integer, is less than the modulus 00789 em[0] = 0x00; 00790 //Block type 0x01 is used for private-key operations 00791 em[1] = 0x01; 00792 00793 //Compute the length of the padding string PS 00794 paddingLength = emLength - hash->oidSize - hash->digestSize - 13; 00795 //Fill the padding string with 0xFF 00796 memset(em + 2, 0xFF, paddingLength); 00797 00798 //Point to the byte that follows PS 00799 i = paddingLength + 2; 00800 //Append a 0x00 octet to PS 00801 em[i++] = 0x00; 00802 00803 //Encode the DigestInfo using ASN.1 00804 em[i++] = ASN1_ENCODING_CONSTRUCTED | ASN1_TYPE_SEQUENCE; 00805 em[i++] = (uint8_t) (hash->oidSize + hash->digestSize + 8); 00806 em[i++] = ASN1_ENCODING_CONSTRUCTED | ASN1_TYPE_SEQUENCE; 00807 em[i++] = (uint8_t) (hash->oidSize + 4); 00808 em[i++] = ASN1_TYPE_OBJECT_IDENTIFIER; 00809 em[i++] = (uint8_t) hash->oidSize; 00810 00811 //Copy the hash algorithm OID 00812 memcpy(em + i, hash->oid, hash->oidSize); 00813 i += hash->oidSize; 00814 00815 //Encode the rest of the ASN.1 structure 00816 em[i++] = ASN1_TYPE_NULL; 00817 em[i++] = 0; 00818 em[i++] = ASN1_TYPE_OCTET_STRING; 00819 em[i++] = (uint8_t) hash->digestSize; 00820 00821 //Append the hash value 00822 memcpy(em + i, digest, hash->digestSize); 00823 00824 //Successful processing 00825 return NO_ERROR; 00826 } 00827 00828 00829 /** 00830 * @brief PKCS #1 v1.5 decoding method 00831 * @param[in] em Encoded message 00832 * @param[in] emLength Length of the encoded message 00833 * @param[out] oid Hash algorithm OID 00834 * @param[out] oidLength Length of the hash algorithm OID 00835 * @param[out] digest Digest value 00836 * @param[out] digestLength Length of the digest value 00837 00838 * @return Error code 00839 **/ 00840 00841 error_t emsaPkcs1v15Decode(const uint8_t *em, size_t emLength, const uint8_t **oid, 00842 size_t *oidLength, const uint8_t **digest, size_t *digestLength) 00843 { 00844 error_t error; 00845 uint_t i; 00846 size_t length; 00847 const uint8_t *data; 00848 Asn1Tag tag; 00849 00850 //Check the length of the encoded message EM 00851 if(emLength < 11) 00852 return ERROR_INVALID_LENGTH; 00853 00854 //The first octet of EM must have a value of 0x00 00855 if(em[0] != 0x00) 00856 return ERROR_UNEXPECTED_VALUE; 00857 //The block type BT shall be 0x01 00858 if(em[1] != 0x01) 00859 return ERROR_UNEXPECTED_VALUE; 00860 00861 //Check the padding string PS 00862 for(i = 2; i < emLength; i++) 00863 { 00864 //A 0x00 octet indicates the end of the padding string 00865 if(em[i] == 0x00) 00866 break; 00867 //Each byte of PS must be set to 0xFF when the block type is 0x01 00868 if(em[i] != 0xFF) 00869 return ERROR_INVALID_PADDING; 00870 } 00871 00872 //Check whether the padding string is properly terminated 00873 if(i >= emLength) 00874 return ERROR_INVALID_PADDING; 00875 //The length of PS cannot be less than 8 octets 00876 if(i < 10) 00877 return ERROR_INVALID_PADDING; 00878 00879 //Point to the DigestInfo structure 00880 data = em + i + 1; 00881 length = emLength - i - 1; 00882 00883 //Read the contents of the DigestInfo structure 00884 error = asn1ReadTag(data, length, &tag); 00885 //Failed to decode the ASN.1 tag? 00886 if(error) 00887 return ERROR_INVALID_TAG; 00888 00889 //Enforce encoding, class and type 00890 if(!tag.constructed || tag.objType != ASN1_TYPE_SEQUENCE) 00891 return ERROR_INVALID_TAG; 00892 00893 //Point to the DigestAlgorithm structure 00894 data = tag.value; 00895 length = tag.length; 00896 00897 //Decode the DigestAlgorithm tag 00898 error = asn1ReadTag(data, length, &tag); 00899 //Failed to decode the ASN.1 tag? 00900 if(error) 00901 return ERROR_INVALID_TAG; 00902 00903 //Enforce encoding, class and type 00904 if(!tag.constructed || tag.objType != ASN1_TYPE_SEQUENCE) 00905 return ERROR_INVALID_TAG; 00906 00907 //Save the location of the next tag 00908 data += tag.totalLength; 00909 length -= tag.totalLength; 00910 00911 //Decode the AlgorithmIdentifier tag 00912 error = asn1ReadTag(tag.value, tag.length, &tag); 00913 //Failed to decode the ASN.1 tag? 00914 if(error) 00915 return ERROR_INVALID_TAG; 00916 00917 //Enforce encoding, class and type 00918 if(tag.constructed || tag.objType != ASN1_TYPE_OBJECT_IDENTIFIER) 00919 return ERROR_INVALID_TAG; 00920 00921 //Save the hash algorithm OID 00922 *oid = tag.value; 00923 *oidLength = tag.length; 00924 00925 //Decode the DigestValue tag 00926 error = asn1ReadTag(data, length, &tag); 00927 //Failed to decode the ASN.1 tag? 00928 if(error) 00929 return ERROR_INVALID_TAG; 00930 00931 //Enforce encoding, class and type 00932 if(tag.constructed || tag.objType != ASN1_TYPE_OCTET_STRING) 00933 return ERROR_INVALID_TAG; 00934 00935 //Save the hash value 00936 *digest = tag.value; 00937 *digestLength = tag.length; 00938 00939 //EM successfully decoded 00940 return NO_ERROR; 00941 } 00942 00943 #endif 00944
Generated on Tue Jul 12 2022 17:10:15 by
1.7.2