Example #1
0
error_t dhGenerateKeyPair(DhContext *context,
   const PrngAlgo *prngAlgo, void *prngContext)
{
   error_t error;
   uint_t k;

   //Debug message
   TRACE_DEBUG("Generating Diffie-Hellman key pair...\r\n");

   //Get the length in bits of the prime p
   k = mpiGetBitLength(&context->params.p);
   //Ensure the length is valid
   if(!k) return ERROR_INVALID_PARAMETER;

   //The private value shall be randomly generated
   error = mpiRand(&context->xa, k, prngAlgo, prngContext);
   //Any error to report?
   if(error) return error;

   //The private value shall be less than p
   if(mpiComp(&context->xa, &context->params.p) >= 0)
   {
      //Shift value to the right
      error = mpiShiftRight(&context->xa, 1);
      //Any error to report?
      if(error) return error;
   }

   //Debug message
   TRACE_DEBUG("  Private value:\r\n");
   TRACE_DEBUG_MPI("    ", &context->xa);

   //Calculate the corresponding public value (ya = g ^ xa mod p)
   error = mpiExpMod(&context->ya, &context->params.g, &context->xa, &context->params.p);
   //Any error to report?
   if(error) return error;

   //Debug message
   TRACE_DEBUG("  Public value:\r\n");
   TRACE_DEBUG_MPI("    ", &context->ya);

   //Check public value
   error = dhCheckPublicKey(&context->params, &context->ya);
   //Weak public value?
   if(error) return error;

   //Public value successfully generated
   return NO_ERROR;
}
Example #2
0
error_t ecLoadDomainParameters(EcDomainParameters *params, const EcCurveInfo *curveInfo)
{
   error_t error;

   //Debug message
   TRACE_DEBUG("Loading %s EC domain parameters...\r\n", curveInfo->name);

   //Curve type
   params->type = curveInfo->type;

   //Import prime modulus
   MPI_CHECK(mpiReadRaw(&params->p, curveInfo->p, curveInfo->pLen));
   //Import parameter a
   MPI_CHECK(mpiReadRaw(&params->a, curveInfo->a, curveInfo->aLen));
   //Import parameter b
   MPI_CHECK(mpiReadRaw(&params->b, curveInfo->b, curveInfo->bLen));
   //Import the x-coordinate of the base point G
   MPI_CHECK(mpiReadRaw(&params->g.x, curveInfo->gx, curveInfo->gxLen));
   //Import the y-coordinate of the base point G
   MPI_CHECK(mpiReadRaw(&params->g.y, curveInfo->gy, curveInfo->gyLen));
   //Import base point order q
   MPI_CHECK(mpiReadRaw(&params->q, curveInfo->q, curveInfo->qLen));

   //Normalize base point G
   MPI_CHECK(mpiSetValue(&params->g.z, 1));

   //Fast modular reduction
   params->mod = curveInfo->mod;

   //Debug message
   TRACE_DEBUG("  p:\r\n");
   TRACE_DEBUG_MPI("    ", &params->p);
   TRACE_DEBUG("  a:\r\n");
   TRACE_DEBUG_MPI("    ", &params->a);
   TRACE_DEBUG("  b:\r\n");
   TRACE_DEBUG_MPI("    ", &params->b);
   TRACE_DEBUG("  Gx:\r\n");
   TRACE_DEBUG_MPI("    ", &params->g.x);
   TRACE_DEBUG("  Gy:\r\n");
   TRACE_DEBUG_MPI("    ", &params->g.y);
   TRACE_DEBUG("  q:\r\n");
   TRACE_DEBUG_MPI("    ", &params->q);

end:
   //Return status code
   return error;
}
Example #3
0
error_t pemReadDhParameters(const char_t *input, size_t length, DhParameters *params)
{
   error_t error;
   size_t i;
   size_t j;
   int_t k;
   char_t *buffer;
   const uint8_t *data;
   Asn1Tag tag;

   //Check parameters
   if(input == NULL && length != 0)
      return ERROR_INVALID_PARAMETER;
   if(params == NULL)
      return ERROR_INVALID_PARAMETER;

   //Search for the beginning tag
   k = pemSearchTag(input, length, "-----BEGIN DH PARAMETERS-----", 29);
   //Failed to find the specified tag?
   if(k < 0) return ERROR_INVALID_SYNTAX;

   //Advance the pointer over the tag
   input += k + 29;
   length -= k + 29;

   //Search for the end tag
   k = pemSearchTag(input, length, "-----END DH PARAMETERS-----", 27);
   //Invalid PEM file?
   if(k <= 0) return ERROR_INVALID_SYNTAX;

   //Length of the PEM structure
   length = k;

   //Allocate a memory buffer to hold the decoded data
   buffer = osMemAlloc(length);
   //Failed to allocate memory?
   if(!buffer) return ERROR_OUT_OF_MEMORY;

   //Copy the contents of the PEM structure
   memcpy(buffer, input, length);

   //Remove carriage returns and line feeds
   for(i = 0, j = 0; i < length; i++)
   {
      if(buffer[i] != '\r' && buffer[i] != '\n')
         buffer[j++] = buffer[i];
   }

   //Start of exception handling block
   do
   {
      //The PEM file is Base64 encoded...
      error = base64Decode(buffer, j, buffer, &length);
      //Failed to decode the file?
      if(error) break;

      //Point to the resulting ASN.1 structure
      data = (uint8_t *) buffer;

      //Display ASN.1 structure
      error = asn1DumpObject(data, length, 0);
      //Any error to report?
      if(error) break;

      //The Diffie-Hellman parameters are encapsulated within a sequence
      error = asn1ReadTag(data, length, &tag);
      //Failed to decode ASN.1 tag?
      if(error) break;

      //Enforce encoding, type and class
      error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE);
      //The tag does not match the criteria?
      if(error) break;

      //Point to the first field of the sequence
      data = tag.value;
      length = tag.length;

      //Read the prime modulus
      error = asn1ReadTag(data, length, &tag);
      //Failed to decode ASN.1 tag?
      if(error) break;

      //Enforce encoding, type and class
      error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER);
      //The tag does not match the criteria?
      if(error) break;

      //Convert the prime modulus to a multiple precision integer
      error = mpiReadRaw(&params->p, tag.value, tag.length);
      //Any error to report?
      if(error) break;

      //Point to the next field
      data += tag.totalLength;
      length -= tag.totalLength;

      //Read the generator
      error = asn1ReadTag(data, length, &tag);
      //Failed to decode ASN.1 tag?
      if(error) break;

      //Enforce encoding, type and class
      error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER);
      //The tag does not match the criteria?
      if(error) break;

      //Convert the generator to a multiple precision integer
      error = mpiReadRaw(&params->g, tag.value, tag.length);
      //Any error to report?
      if(error) break;

      //Debug message
      TRACE_DEBUG("Diffie-Hellman parameters:\r\n");
      TRACE_DEBUG("  Prime modulus:\r\n");
      TRACE_DEBUG_MPI("    ", &params->p);
      TRACE_DEBUG("  Generator:\r\n");
      TRACE_DEBUG_MPI("    ", &params->g);

      //End of exception handling block
   } while(0);

   //Release previously allocated memory
   osMemFree(buffer);

   //Clean up side effects if necessary
   if(error)
      dhFreeParameters(params);

   //Return status code
   return error;
}
Example #4
0
error_t rsassaPkcs1v15Verify(const RsaPublicKey *key, const HashAlgo *hash,
   const uint8_t *digest, const uint8_t *signature, size_t signatureLength)
{
   error_t error;
   uint_t k;
   uint8_t *em;
   const uint8_t *oid;
   size_t oidLength;
   const uint8_t *d;
   size_t dLength;
   Mpi s;
   Mpi m;

   //Check parameters
   if(key == NULL || hash == NULL || digest == NULL || signature == NULL)
      return ERROR_INVALID_PARAMETER;

   //Debug message
   TRACE_DEBUG("RSA PKCS #1 v1.5 signature verification...\r\n");
   TRACE_DEBUG("  Modulus:\r\n");
   TRACE_DEBUG_MPI("    ", &key->n);
   TRACE_DEBUG("  Public exponent:\r\n");
   TRACE_DEBUG_MPI("    ", &key->e);
   TRACE_DEBUG("  Message digest:\r\n");
   TRACE_DEBUG_ARRAY("    ", digest, hash->digestSize);
   TRACE_DEBUG("  Signature:\r\n");
   TRACE_DEBUG_ARRAY("    ", signature, signatureLength);

   //Initialize multiple-precision integers
   mpiInit(&s);
   mpiInit(&m);

   //Get the length in octets of the modulus n
   k = mpiGetByteLength(&key->n);

   //Check the length of the signature
   if(signatureLength != k)
      return ERROR_INVALID_LENGTH;

   //Allocate a memory buffer to hold the encoded message
   em = osAllocMem(k);
   //Failed to allocate memory?
   if(!em) return ERROR_OUT_OF_MEMORY;

   //Start of exception handling block
   do
   {
      //Convert the signature to an integer signature representative s
      error = mpiReadRaw(&s, signature, signatureLength);
      //Conversion failed?
      if(error) break;

      //Apply the RSAVP1 verification primitive
      error = rsavp1(key, &s, &m);
      //Any error to report?
      if(error) break;

      //Convert the message representative m to an encoded message EM of length k octets
      error = mpiWriteRaw(&m, em, k);
      //Conversion failed?
      if(error) break;

      //Debug message
      TRACE_DEBUG("  Encoded message\r\n");
      TRACE_DEBUG_ARRAY("    ", em, k);

      //Parse the encoded message EM
      error = emsaPkcs1v15Decode(em, k, &oid, &oidLength, &d, &dLength);
      //Any error to report?
      if(error) break;

      //Assume an error...
      error = ERROR_INVALID_SIGNATURE_ALGO;
      //Ensure the hash algorithm identifier matches the OID
      if(oidComp(oid, oidLength, hash->oid, hash->oidSize))
         break;
      //Check the length of the digest
      if(dLength != hash->digestSize)
         break;

      //Compare the message digest
      error = memcmp(digest, d, dLength) ? ERROR_INVALID_SIGNATURE : NO_ERROR;

      //End of exception handling block
   } while(0);

   //Release multiple precision integers
   mpiFree(&s);
   mpiFree(&m);
   //Free previously allocated memory
   osFreeMem(em);

   //Return status code
   return error;
}
Example #5
0
error_t rsassaPkcs1v15Sign(const RsaPrivateKey *key, const HashAlgo *hash,
   const uint8_t *digest, uint8_t *signature, size_t *signatureLength)
{
   error_t error;
   uint_t k;
   uint8_t *em;
   Mpi m;
   Mpi s;

   //Check parameters
   if(key == NULL || hash == NULL || digest == NULL)
      return ERROR_INVALID_PARAMETER;
   if(signature == NULL || signatureLength == NULL)
      return ERROR_INVALID_PARAMETER;

   //Debug message
   TRACE_DEBUG("RSA PKCS #1 v1.5 signature generation...\r\n");
   TRACE_DEBUG("  Modulus:\r\n");
   TRACE_DEBUG_MPI("    ", &key->n);
   TRACE_DEBUG("  Public exponent:\r\n");
   TRACE_DEBUG_MPI("    ", &key->e);
   TRACE_DEBUG("  Private exponent:\r\n");
   TRACE_DEBUG_MPI("    ", &key->d);
   TRACE_DEBUG("  Prime 1:\r\n");
   TRACE_DEBUG_MPI("    ", &key->p);
   TRACE_DEBUG("  Prime 2:\r\n");
   TRACE_DEBUG_MPI("    ", &key->q);
   TRACE_DEBUG("  Prime exponent 1:\r\n");
   TRACE_DEBUG_MPI("    ", &key->dp);
   TRACE_DEBUG("  Prime exponent 2:\r\n");
   TRACE_DEBUG_MPI("    ", &key->dq);
   TRACE_DEBUG("  Coefficient:\r\n");
   TRACE_DEBUG_MPI("    ", &key->qinv);
   TRACE_DEBUG("  Message digest:\r\n");
   TRACE_DEBUG_ARRAY("    ", digest, hash->digestSize);

   //Initialize multiple-precision integers
   mpiInit(&m);
   mpiInit(&s);

   //Get the length in octets of the modulus n
   k = mpiGetByteLength(&key->n);
   //Point to the buffer where the encoded message EM will be generated
   em = signature;

   //Apply the EMSA-PKCS1-v1.5 encoding operation
   error = emsaPkcs1v15Encode(hash, digest, em, k);
   //Any error to report?
   if(error) return error;

   //Debug message
   TRACE_DEBUG("  Encoded message\r\n");
   TRACE_DEBUG_ARRAY("    ", em, k);

   //Start of exception handling block
   do
   {
      //Convert the encoded message EM to an integer message representative m
      error = mpiReadRaw(&m, em, k);
      //Conversion failed?
      if(error) break;

      //Apply the RSASP1 signature primitive
      error = rsasp1(key, &m, &s);
      //Any error to report?
      if(error) break;

      //Convert the signature representative s to a signature of length k octets
      error = mpiWriteRaw(&s, signature, k);
      //Conversion failed?
      if(error) break;

      //Length of the resulting signature
      *signatureLength = k;

      //Debug message
      TRACE_DEBUG("  Signature:\r\n");
      TRACE_DEBUG_ARRAY("    ", signature, *signatureLength);

      //End of exception handling block
   } while(0);

   //Free previously allocated memory
   mpiFree(&m);
   mpiFree(&s);

   //Return status code
   return error;
}
Example #6
0
error_t rsaesPkcs1v15Decrypt(const RsaPrivateKey *key, const uint8_t *ciphertext,
   size_t ciphertextLength, uint8_t *message, size_t messageSize, size_t *messageLength)
{
   error_t error;
   uint_t i;
   uint_t k;
   uint8_t *em;
   Mpi c;
   Mpi m;

   //Check parameters
   if(key == NULL || ciphertext == NULL)
      return ERROR_INVALID_PARAMETER;
   if(message == NULL || messageLength == NULL)
      return ERROR_INVALID_PARAMETER;

   //Debug message
   TRACE_DEBUG("RSA PKCS #1 v1.5 decryption...\r\n");
   TRACE_DEBUG("  Modulus:\r\n");
   TRACE_DEBUG_MPI("    ", &key->n);
   TRACE_DEBUG("  Public exponent:\r\n");
   TRACE_DEBUG_MPI("    ", &key->e);
   TRACE_DEBUG("  Private exponent:\r\n");
   TRACE_DEBUG_MPI("    ", &key->d);
   TRACE_DEBUG("  Prime 1:\r\n");
   TRACE_DEBUG_MPI("    ", &key->p);
   TRACE_DEBUG("  Prime 2:\r\n");
   TRACE_DEBUG_MPI("    ", &key->q);
   TRACE_DEBUG("  Prime exponent 1:\r\n");
   TRACE_DEBUG_MPI("    ", &key->dp);
   TRACE_DEBUG("  Prime exponent 2:\r\n");
   TRACE_DEBUG_MPI("    ", &key->dq);
   TRACE_DEBUG("  Coefficient:\r\n");
   TRACE_DEBUG_MPI("    ", &key->qinv);
   TRACE_DEBUG("  Ciphertext:\r\n");
   TRACE_DEBUG_ARRAY("    ", ciphertext, ciphertextLength);

   //Initialize multiple-precision integers
   mpiInit(&c);
   mpiInit(&m);

   //Get the length in octets of the modulus n
   k = mpiGetByteLength(&key->n);

   //Check the length of the ciphertext
   if(ciphertextLength != k || ciphertextLength < 11)
      return ERROR_INVALID_LENGTH;

   //Allocate a buffer to store the encoded message EM
   em = osAllocMem(k);
   //Failed to allocate memory?
   if(!em) return ERROR_OUT_OF_MEMORY;

   //Start of exception handling block
   do
   {
      //Convert the ciphertext to an integer ciphertext representative c
      error = mpiReadRaw(&c, ciphertext, ciphertextLength);
      //Conversion failed?
      if(error) break;

      //Apply the RSADP decryption primitive
      error = rsadp(key, &c, &m);
      //Any error to report?
      if(error) break;

      //Convert the message representative m to an encoded message EM of length k octets
      error = mpiWriteRaw(&m, em, k);
      //Conversion failed?
      if(error) break;

      //Debug message
      TRACE_DEBUG("  Encoded message\r\n");
      TRACE_DEBUG_ARRAY("    ", em, k);

      //The first octet of EM must have a value of 0x00
      //and the block type BT shall be 0x02
      if(em[0] != 0x00 || em[1] != 0x02)
      {
         //Report an error
         error = ERROR_UNEXPECTED_VALUE;
         break;
      }

      //An octet with hexadecimal value 0x00 is used to separate PS from M
      for(i = 2; i < k && em[i] != 0x00; i++);

      //Check whether the padding string is valid
      if(i < 10 || i >= k)
      {
         //Report an error
         error = ERROR_INVALID_PADDING;
         break;
      }

      //Ensure that the output buffer is large enough
      if(messageSize < (k - i - 1))
      {
         //Report an error
         error = ERROR_INVALID_LENGTH;
         break;
      }

      //Recover the length of the message
      *messageLength = k - i - 1;
      //Copy the message contents
      memcpy(message, em + i + 1, *messageLength);

      //Debug message
      TRACE_DEBUG("  Message:\r\n");
      TRACE_DEBUG_ARRAY("    ", message, *messageLength);

      //End of exception handling block
   } while(0);

   //Release multiple precision integers
   mpiFree(&c);
   mpiFree(&m);
   //Free previously allocated memory
   osFreeMem(em);

   //Return status code
   return error;
}
Example #7
0
error_t rsaesPkcs1v15Encrypt(const PrngAlgo *prngAlgo, void *prngContext, const RsaPublicKey *key,
   const uint8_t *message, size_t messageLength, uint8_t *ciphertext, size_t *ciphertextLength)
{
   error_t error;
   uint_t i;
   uint_t j;
   uint_t k;
   uint_t n;
   uint8_t *p;
   Mpi m;
   Mpi c;

   //Check parameters
   if(key == NULL || message == NULL)
      return ERROR_INVALID_PARAMETER;
   if(ciphertext == NULL || ciphertextLength == NULL)
      return ERROR_INVALID_PARAMETER;

   //Debug message
   TRACE_DEBUG("RSA PKCS #1 v1.5 encryption...\r\n");
   TRACE_DEBUG("  Modulus:\r\n");
   TRACE_DEBUG_MPI("    ", &key->n);
   TRACE_DEBUG("  Public exponent:\r\n");
   TRACE_DEBUG_MPI("    ", &key->e);
   TRACE_DEBUG("  Message:\r\n");
   TRACE_DEBUG_ARRAY("    ", message, messageLength);

   //Initialize multiple-precision integers
   mpiInit(&m);
   mpiInit(&c);

   //Get the length in octets of the modulus n
   k = mpiGetByteLength(&key->n);

   //Check the length of the message
   if((messageLength + 11) > k)
      return ERROR_INVALID_LENGTH;

   //Point to the buffer where the encoded message EM will be formatted
   p = ciphertext;

   //The leading 0x00 octet ensures that the encoded message,
   //converted to an integer, is less than the modulus
   *(p++) = 0x00;
   //For a public-key operation, the block type BT shall be 0x02
   *(p++) = 0x02;

   //Length of the padding string PS
   n = k - messageLength - 3;

   //Generate the padding string (pseudo-randomly generated non-zero octets)
   while(n > 0)
   {
      //Generate random data
      error = prngAlgo->read(prngContext, p, n);
      //Any error to report?
      if(error) return error;

      //Parse the resulting octet string
      for(i = 0, j = 0; j < n; j++)
      {
         //Strip any byte with a value of zero
         if(p[j] != 0)
            p[i++] = p[j];
      }

      //Advance data pointer
      p += i;
      n -= i;
   }

   //Append a 0x00 octet to the padding string
   *(p++) = 0x00;
   //Copy the message to be encrypted
   memcpy(p, message, messageLength);

   //Rewind to the beginning of the encoded message
   p = ciphertext;

   //Debug message
   TRACE_DEBUG("  Encoded message\r\n");
   TRACE_DEBUG_ARRAY("    ", p, k);

   //Start of exception handling block
   do
   {
      //Convert the encoded message EM to an integer message representative m
      error = mpiReadRaw(&m, p, k);
      //Conversion failed?
      if(error) break;

      //Apply the RSAEP encryption primitive
      error = rsaep(key, &m, &c);
      //Any error to report?
      if(error) break;

      //Convert the ciphertext representative c to a ciphertext of length k octets
      error = mpiWriteRaw(&c, ciphertext, k);
      //Conversion failed?
      if(error) break;

      //Length of the resulting ciphertext
      *ciphertextLength = k;

      //Debug message
      TRACE_DEBUG("  Ciphertext:\r\n");
      TRACE_DEBUG_ARRAY("    ", ciphertext, *ciphertextLength);

      //End of exception handling block
   } while(0);

   //Free previously allocated memory
   mpiFree(&m);
   mpiFree(&c);

   //Return status code
   return error;
}