Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rsa.c Source File

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