modules/libmar/verify/cryptox.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #ifdef XP_WIN
     6 #ifndef WIN32_LEAN_AND_MEAN
     7 #define WIN32_LEAN_AND_MEAN
     8 #endif
     9 #endif
    11 #include <stdlib.h>
    12 #include "cryptox.h"
    14 #if defined(MAR_NSS)
    16 /** 
    17  * Loads the public key for the specified cert name from the NSS store.
    18  * 
    19  * @param certName The cert name to find.
    20  * @param publicKey Out parameter for the public key to use.
    21  * @param cert      Out parameter for the certificate to use.
    22  * @return CryptoX_Success on success, CryptoX_Error on error.
    23 */
    24 CryptoX_Result
    25 NSS_LoadPublicKey(const char *certNickname, 
    26                   SECKEYPublicKey **publicKey, 
    27                   CERTCertificate **cert)
    28 {
    29   secuPWData pwdata = { PW_NONE, 0 };
    30   if (!cert || !publicKey || !cert) {
    31     return CryptoX_Error;
    32   }
    34   /* Get the cert and embedded public key out of the database */
    35   *cert = PK11_FindCertFromNickname(certNickname, &pwdata);
    36   if (!*cert) {
    37     return CryptoX_Error;
    38   }
    39   *publicKey = CERT_ExtractPublicKey(*cert);
    40   if (!*publicKey) {
    41     CERT_DestroyCertificate(*cert);
    42     return CryptoX_Error;
    43   }
    44   return CryptoX_Success;
    45 }
    47 CryptoX_Result
    48 NSS_VerifyBegin(VFYContext **ctx, 
    49                 SECKEYPublicKey * const *publicKey)
    50 {
    51   SECStatus status;
    52   if (!ctx || !publicKey || !*publicKey) {
    53     return CryptoX_Error;
    54   }
    56   /* Check that the key length is large enough for our requirements */
    57   if ((SECKEY_PublicKeyStrength(*publicKey) * 8) < 
    58       XP_MIN_SIGNATURE_LEN_IN_BYTES) {
    59     fprintf(stderr, "ERROR: Key length must be >= %d bytes\n", 
    60             XP_MIN_SIGNATURE_LEN_IN_BYTES);
    61     return CryptoX_Error;
    62   }
    64   *ctx = VFY_CreateContext(*publicKey, NULL, 
    65                            SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE, NULL);
    66   if (*ctx == NULL) {
    67     return CryptoX_Error;
    68   }
    70   status = VFY_Begin(*ctx);
    71   return SECSuccess == status ? CryptoX_Success : CryptoX_Error;
    72 }
    74 /**
    75  * Verifies if a verify context matches the passed in signature.
    76  *
    77  * @param ctx          The verify context that the signature should match.
    78  * @param signature    The signature to match.
    79  * @param signatureLen The length of the signature.
    80  * @return CryptoX_Success on success, CryptoX_Error on error.
    81 */
    82 CryptoX_Result
    83 NSS_VerifySignature(VFYContext * const *ctx, 
    84                     const unsigned char *signature, 
    85                     unsigned int signatureLen)
    86 {
    87   SECItem signedItem;
    88   SECStatus status;
    89   if (!ctx || !signature || !*ctx) {
    90     return CryptoX_Error;
    91   }
    93   signedItem.len = signatureLen;
    94   signedItem.data = (unsigned char*)signature;
    95   status = VFY_EndWithSignature(*ctx, &signedItem);
    96   return SECSuccess == status ? CryptoX_Success : CryptoX_Error;
    97 }
    99 #elif defined(XP_WIN)
   100 /**
   101  * Verifies if a signature + public key matches a hash context.
   102  *
   103  * @param hash      The hash context that the signature should match.
   104  * @param pubKey    The public key to use on the signature.
   105  * @param signature The signature to check.
   106  * @param signatureLen The length of the signature.
   107  * @return CryptoX_Success on success, CryptoX_Error on error.
   108 */
   109 CryptoX_Result
   110 CyprtoAPI_VerifySignature(HCRYPTHASH *hash, 
   111                           HCRYPTKEY *pubKey,
   112                           const BYTE *signature, 
   113                           DWORD signatureLen)
   114 {
   115   DWORD i;
   116   BOOL result;
   117 /* Windows APIs expect the bytes in the signature to be in little-endian 
   118  * order, but we write the signature in big-endian order.  Other APIs like 
   119  * NSS and OpenSSL expect big-endian order.
   120  */
   121   BYTE *signatureReversed;
   122   if (!hash || !pubKey || !signature || signatureLen < 1) {
   123     return CryptoX_Error;
   124   }
   126   signatureReversed = malloc(signatureLen);
   127   if (!signatureReversed) {
   128     return CryptoX_Error;
   129   }
   131   for (i = 0; i < signatureLen; i++) {
   132     signatureReversed[i] = signature[signatureLen - 1 - i]; 
   133   }
   134   result = CryptVerifySignature(*hash, signatureReversed,
   135                                 signatureLen, *pubKey, NULL, 0);
   136   free(signatureReversed);
   137   return result ? CryptoX_Success : CryptoX_Error;
   138 }
   140 /** 
   141  * Obtains the public key for the passed in cert data
   142  * 
   143  * @param provider       The cyrto provider
   144  * @param certData       Data of the certificate to extract the public key from
   145  * @param sizeOfCertData The size of the certData buffer
   146  * @param certStore      Pointer to the handle of the certificate store to use
   147  * @param CryptoX_Success on success
   148 */
   149 CryptoX_Result
   150 CryptoAPI_LoadPublicKey(HCRYPTPROV provider, 
   151                         BYTE *certData,
   152                         DWORD sizeOfCertData,
   153                         HCRYPTKEY *publicKey,
   154                         HCERTSTORE *certStore)
   155 {
   156   CRYPT_DATA_BLOB blob;
   157   CERT_CONTEXT *context;
   158   if (!provider || !certData || !publicKey || !certStore) {
   159     return CryptoX_Error;
   160   }
   162   blob.cbData = sizeOfCertData;
   163   blob.pbData = certData;
   164   if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, 
   165                         CERT_QUERY_CONTENT_FLAG_CERT, 
   166                         CERT_QUERY_FORMAT_FLAG_BINARY, 
   167                         0, NULL, NULL, NULL, 
   168                         certStore, NULL, (const void **)&context)) {
   169     return CryptoX_Error;
   170   }
   172   if (!CryptImportPublicKeyInfo(provider, 
   173                                 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
   174                                 &context->pCertInfo->SubjectPublicKeyInfo,
   175                                 publicKey)) {
   176     CertFreeCertificateContext(context);
   177     return CryptoX_Error;
   178   }
   180   CertFreeCertificateContext(context);
   181   return CryptoX_Success;
   182 }
   184 /* Try to acquire context in this way:
   185   * 1. Enhanced provider without creating a new key set
   186   * 2. Enhanced provider with creating a new key set
   187   * 3. Default provider without creating a new key set
   188   * 4. Default provider without creating a new key set
   189   * #2 and #4 should not be needed because of the CRYPT_VERIFYCONTEXT, 
   190   * but we add it just in case.
   191   *
   192   * @param provider Out parameter containing the provider handle.
   193   * @return CryptoX_Success on success, CryptoX_Error on error.
   194  */
   195 CryptoX_Result
   196 CryptoAPI_InitCryptoContext(HCRYPTPROV *provider)
   197 {
   198   if (!CryptAcquireContext(provider, 
   199                            NULL, 
   200                            MS_ENHANCED_PROV, 
   201                            PROV_RSA_FULL, 
   202                            CRYPT_VERIFYCONTEXT)) {
   203     if (!CryptAcquireContext(provider, 
   204                              NULL, 
   205                              MS_ENHANCED_PROV, 
   206                              PROV_RSA_FULL, 
   207                              CRYPT_NEWKEYSET | CRYPT_VERIFYCONTEXT)) {
   208       if (!CryptAcquireContext(provider, 
   209                                NULL, 
   210                                NULL, 
   211                                PROV_RSA_FULL, 
   212                                CRYPT_VERIFYCONTEXT)) {
   213         if (!CryptAcquireContext(provider, 
   214                                  NULL, 
   215                                  NULL, 
   216                                  PROV_RSA_FULL, 
   217                                  CRYPT_NEWKEYSET | CRYPT_VERIFYCONTEXT)) {
   218           *provider = CryptoX_InvalidHandleValue;
   219           return CryptoX_Error;
   220         }
   221       }
   222     }
   223   }
   224   return CryptoX_Success;
   225 }
   227 /** 
   228   * Begins a signature verification hash context
   229   *
   230   * @param provider The crypt provider to use
   231   * @param hash     Out parameter for a handle to the hash context
   232   * @return CryptoX_Success on success, CryptoX_Error on error.
   233 */
   234 CryptoX_Result
   235 CryptoAPI_VerifyBegin(HCRYPTPROV provider, HCRYPTHASH* hash)
   236 {
   237   BOOL result;
   238   if (!provider || !hash) {
   239     return CryptoX_Error;
   240   }
   242   *hash = (HCRYPTHASH)NULL;
   243   result = CryptCreateHash(provider, CALG_SHA1,
   244                            0, 0, hash);
   245   return result ? CryptoX_Success : CryptoX_Error;
   246 }
   248 /** 
   249   * Updates a signature verification hash context
   250   *
   251   * @param hash The hash context to udpate
   252   * @param buf  The buffer to update the hash context with
   253   * @param len The size of the passed in buffer
   254   * @return CryptoX_Success on success, CryptoX_Error on error.
   255 */
   256 CryptoX_Result
   257 CryptoAPI_VerifyUpdate(HCRYPTHASH* hash, BYTE *buf, DWORD len)
   258 {
   259   BOOL result;
   260   if (!hash || !buf) {
   261     return CryptoX_Error;
   262   }
   264   result = CryptHashData(*hash, buf, len, 0);
   265   return result ? CryptoX_Success : CryptoX_Error;
   266 }
   268 #endif

mercurial