Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
rsa.c
Go to the documentation of this file.
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
