Xuyi Wang / wolfcrypt

Dependents:   OS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers signature.c Source File

signature.c

00001 /* signature.c
00002  *
00003  * Copyright (C) 2006-2017 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 #include <wolfcrypt/settings.h>
00028 #include <wolfcrypt/signature.h>
00029 #include <wolfcrypt/error-crypt.h>
00030 #include <wolfcrypt/logging.h>
00031 #ifndef NO_ASN
00032 #include <wolfcrypt/asn.h>
00033 #endif
00034 #ifdef HAVE_ECC
00035 #include <wolfcrypt/ecc.h>
00036 #endif
00037 #ifndef NO_RSA
00038 #include <wolfcrypt/rsa.h>
00039 #endif
00040 
00041 /* If ECC and RSA are disabled then disable signature wrapper */
00042 #if (!defined(HAVE_ECC) || (defined(HAVE_ECC) && !defined(HAVE_ECC_SIGN) \
00043     && !defined(HAVE_ECC_VERIFY))) && defined(NO_RSA)
00044     #undef NO_SIG_WRAPPER
00045     #define NO_SIG_WRAPPER
00046 #endif
00047 
00048 /* Signature wrapper disabled check */
00049 #ifndef NO_SIG_WRAPPER
00050 
00051 #if !defined(NO_RSA) && !defined(NO_ASN)
00052 static int wc_SignatureDerEncode(enum wc_HashType hash_type, byte** hash_data,
00053     word32* hash_len)
00054 {
00055     int ret = wc_HashGetOID(hash_type);
00056     if (ret > 0) {
00057         int oid = ret;
00058 
00059         /* Allocate buffer for hash and max DER encoded */
00060         word32 digest_len = *hash_len + MAX_DER_DIGEST_SZ;
00061         byte *digest_buf = (byte*)XMALLOC(digest_len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00062         if (digest_buf) {
00063             ret = wc_EncodeSignature(digest_buf, *hash_data, *hash_len, oid);
00064             if (ret > 0) {
00065                 digest_len = ret;
00066                 ret = 0;
00067 
00068                 /* Replace hash with digest (DER encoding + hash) */
00069                 XFREE(*hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00070                 *hash_data = digest_buf;
00071                 *hash_len = digest_len;
00072             }
00073             else {
00074                 XFREE(digest_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00075             }
00076         }
00077         else {
00078             ret = MEMORY_E;
00079         }
00080     }
00081     return ret;
00082 }
00083 #endif /* !NO_RSA && !NO_ASN */
00084 
00085 int wc_SignatureGetSize(enum wc_SignatureType sig_type,
00086     const void* key, word32 key_len)
00087 {
00088     int sig_len = BAD_FUNC_ARG;
00089 
00090     /* Suppress possible unused args if all signature types are disabled */
00091     (void)key;
00092     (void)key_len;
00093 
00094     switch(sig_type) {
00095         case WC_SIGNATURE_TYPE_ECC:
00096 #ifdef HAVE_ECC
00097             /* Sanity check that void* key is at least ecc_key in size */
00098             if (key_len >= sizeof(ecc_key)) {
00099                 sig_len = wc_ecc_sig_size((ecc_key*)key);
00100             }
00101             else {
00102                 WOLFSSL_MSG("wc_SignatureGetSize: Invalid ECC key size");
00103             }
00104 #else
00105             sig_len = SIG_TYPE_E;
00106 #endif
00107             break;
00108 
00109         case WC_SIGNATURE_TYPE_RSA_W_ENC:
00110         case WC_SIGNATURE_TYPE_RSA:
00111 #ifndef NO_RSA
00112             /* Sanity check that void* key is at least RsaKey in size */
00113             if (key_len >= sizeof(RsaKey)) {
00114                 sig_len = wc_RsaEncryptSize((RsaKey*)key);
00115             }
00116             else {
00117                 WOLFSSL_MSG("wc_SignatureGetSize: Invalid RsaKey key size");
00118             }
00119 #else
00120             sig_len = SIG_TYPE_E;
00121 #endif
00122             break;
00123 
00124         case WC_SIGNATURE_TYPE_NONE:
00125         default:
00126             sig_len = BAD_FUNC_ARG;
00127             break;
00128     }
00129     return sig_len;
00130 }
00131 
00132 int wc_SignatureVerifyHash(
00133     enum wc_HashType hash_type, enum wc_SignatureType sig_type,
00134     const byte* hash_data, word32 hash_len,
00135     const byte* sig, word32 sig_len,
00136     const void* key, word32 key_len)
00137 {
00138     int ret;
00139 
00140     /* Check arguments */
00141     if (hash_data == NULL || hash_len <= 0 ||
00142         sig == NULL || sig_len <= 0 ||
00143         key == NULL || key_len <= 0) {
00144         return BAD_FUNC_ARG;
00145     }
00146 
00147     /* Validate signature len (1 to max is okay) */
00148     if ((int)sig_len > wc_SignatureGetSize(sig_type, key, key_len)) {
00149         WOLFSSL_MSG("wc_SignatureVerify: Invalid sig type/len");
00150         return BAD_FUNC_ARG;
00151     }
00152 
00153     /* Validate hash size */
00154     ret = wc_HashGetDigestSize(hash_type);
00155     if (ret < 0) {
00156         WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len");
00157         return ret;
00158     }
00159     ret = 0;
00160 
00161     /* Verify signature using hash */
00162     switch (sig_type) {
00163         case WC_SIGNATURE_TYPE_ECC:
00164         {
00165 #if defined(HAVE_ECC) && defined(HAVE_ECC_VERIFY)
00166             int is_valid_sig = 0;
00167 
00168             /* Perform verification of signature using provided ECC key */
00169             do {
00170             #ifdef WOLFSSL_ASYNC_CRYPT
00171                 ret = wc_AsyncWait(ret, &((ecc_key*)key)->asyncDev,
00172                     WC_ASYNC_FLAG_CALL_AGAIN);
00173             #endif
00174             if (ret >= 0)
00175                 ret = wc_ecc_verify_hash(sig, sig_len, hash_data, hash_len,
00176                     &is_valid_sig, (ecc_key*)key);
00177             } while (ret == WC_PENDING_E);
00178             if (ret != 0 || is_valid_sig != 1) {
00179                 ret = SIG_VERIFY_E;
00180             }
00181 #else
00182             ret = SIG_TYPE_E;
00183 #endif
00184             break;
00185         }
00186 
00187         case WC_SIGNATURE_TYPE_RSA_W_ENC:
00188         case WC_SIGNATURE_TYPE_RSA:
00189         {
00190 #ifndef NO_RSA
00191             word32 plain_len = hash_len;
00192             byte *plain_data;
00193 
00194             /* Make sure the plain text output is at least key size */
00195             if (plain_len < sig_len) {
00196                 plain_len = sig_len;
00197             }
00198             plain_data = (byte*)XMALLOC(plain_len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00199             if (plain_data) {
00200                 /* Perform verification of signature using provided RSA key */
00201                 do {
00202                 #ifdef WOLFSSL_ASYNC_CRYPT
00203                     ret = wc_AsyncWait(ret, &((RsaKey*)key)->asyncDev,
00204                         WC_ASYNC_FLAG_CALL_AGAIN);
00205                 #endif
00206                 if (ret >= 0)
00207                     ret = wc_RsaSSL_Verify(sig, sig_len, plain_data,
00208                         plain_len, (RsaKey*)key);
00209                 } while (ret == WC_PENDING_E);
00210                 if (ret >= 0) {
00211                     if ((word32)ret == hash_len &&
00212                             XMEMCMP(plain_data, hash_data, hash_len) == 0) {
00213                         ret = 0; /* Success */
00214                     }
00215                     else {
00216                         WOLFSSL_MSG("RSA Signature Verify difference!");
00217                         ret = SIG_VERIFY_E;
00218                     }
00219                 }
00220                 XFREE(plain_data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00221             }
00222             else {
00223                 ret = MEMORY_E;
00224             }
00225 #else
00226             ret = SIG_TYPE_E;
00227 #endif
00228             break;
00229         }
00230 
00231         case WC_SIGNATURE_TYPE_NONE:
00232         default:
00233             ret = BAD_FUNC_ARG;
00234             break;
00235     }
00236 
00237     return ret;
00238 }
00239 
00240 int wc_SignatureVerify(
00241     enum wc_HashType hash_type, enum wc_SignatureType sig_type,
00242     const byte* data, word32 data_len,
00243     const byte* sig, word32 sig_len,
00244     const void* key, word32 key_len)
00245 {
00246     int ret;
00247     word32 hash_len;
00248     byte *hash_data = NULL;
00249 
00250     /* Check arguments */
00251     if (data == NULL || data_len <= 0 ||
00252         sig == NULL || sig_len <= 0 ||
00253         key == NULL || key_len <= 0) {
00254         return BAD_FUNC_ARG;
00255     }
00256 
00257     /* Validate signature len (1 to max is okay) */
00258     if ((int)sig_len > wc_SignatureGetSize(sig_type, key, key_len)) {
00259         WOLFSSL_MSG("wc_SignatureVerify: Invalid sig type/len");
00260         return BAD_FUNC_ARG;
00261     }
00262 
00263     /* Validate hash size */
00264     ret = wc_HashGetDigestSize(hash_type);
00265     if (ret < 0) {
00266         WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len");
00267         return ret;
00268     }
00269     hash_len = ret;
00270 
00271     /* Allocate temporary buffer for hash data */
00272     hash_data = (byte*)XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00273     if (hash_data == NULL) {
00274         return MEMORY_E;
00275     }
00276 
00277     /* Perform hash of data */
00278     ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len);
00279     if (ret == 0) {
00280         /* Handle RSA with DER encoding */
00281         if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) {
00282         #if defined(NO_RSA) || defined(NO_ASN)
00283             ret = SIG_TYPE_E;
00284         #else
00285             ret = wc_SignatureDerEncode(hash_type, &hash_data, &hash_len);
00286         #endif
00287         }
00288 
00289         if (ret == 0) {
00290             /* Verify signature using hash */
00291             ret = wc_SignatureVerifyHash(hash_type, sig_type,
00292                 hash_data, hash_len, sig, sig_len, key, key_len);
00293         }
00294     }
00295 
00296     if (hash_data) {
00297         XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00298     }
00299 
00300     return ret;
00301 }
00302 
00303 
00304 int wc_SignatureGenerateHash(
00305     enum wc_HashType hash_type, enum wc_SignatureType sig_type,
00306     const byte* hash_data, word32 hash_len,
00307     byte* sig, word32 *sig_len,
00308     const void* key, word32 key_len, WC_RNG* rng)
00309 {
00310     int ret;
00311 
00312     /* Suppress possible unused arg if all signature types are disabled */
00313     (void)rng;
00314 
00315     /* Check arguments */
00316     if (hash_data == NULL || hash_len <= 0 ||
00317         sig == NULL || sig_len == NULL || *sig_len <= 0 ||
00318         key == NULL || key_len <= 0) {
00319         return BAD_FUNC_ARG;
00320     }
00321 
00322     /* Validate signature len (needs to be at least max) */
00323     if ((int)*sig_len < wc_SignatureGetSize(sig_type, key, key_len)) {
00324         WOLFSSL_MSG("wc_SignatureGenerate: Invalid sig type/len");
00325         return BAD_FUNC_ARG;
00326     }
00327 
00328     /* Validate hash size */
00329     ret = wc_HashGetDigestSize(hash_type);
00330     if (ret < 0) {
00331         WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len");
00332         return ret;
00333     }
00334     ret = 0;
00335 
00336     /* Create signature using hash as data */
00337     switch (sig_type) {
00338         case WC_SIGNATURE_TYPE_ECC:
00339 #if defined(HAVE_ECC) && defined(HAVE_ECC_SIGN)
00340             /* Create signature using provided ECC key */
00341             do {
00342             #ifdef WOLFSSL_ASYNC_CRYPT
00343                 ret = wc_AsyncWait(ret, &((ecc_key*)key)->asyncDev,
00344                     WC_ASYNC_FLAG_CALL_AGAIN);
00345             #endif
00346             if (ret >= 0)
00347                 ret = wc_ecc_sign_hash(hash_data, hash_len, sig, sig_len,
00348                     rng, (ecc_key*)key);
00349             } while (ret == WC_PENDING_E);
00350 #else
00351             ret = SIG_TYPE_E;
00352 #endif
00353             break;
00354 
00355         case WC_SIGNATURE_TYPE_RSA_W_ENC:
00356         case WC_SIGNATURE_TYPE_RSA:
00357 #ifndef NO_RSA
00358             /* Create signature using provided RSA key */
00359             do {
00360             #ifdef WOLFSSL_ASYNC_CRYPT
00361                 ret = wc_AsyncWait(ret, &((RsaKey*)key)->asyncDev,
00362                     WC_ASYNC_FLAG_CALL_AGAIN);
00363             #endif
00364                 if (ret >= 0)
00365                     ret = wc_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len,
00366                         (RsaKey*)key, rng);
00367             } while (ret == WC_PENDING_E);
00368             if (ret >= 0) {
00369                 *sig_len = ret;
00370                 ret = 0; /* Success */
00371             }
00372 #else
00373             ret = SIG_TYPE_E;
00374 #endif
00375             break;
00376 
00377         case WC_SIGNATURE_TYPE_NONE:
00378         default:
00379             ret = BAD_FUNC_ARG;
00380             break;
00381     }
00382 
00383     return ret;
00384 }
00385 
00386 int wc_SignatureGenerate(
00387     enum wc_HashType hash_type, enum wc_SignatureType sig_type,
00388     const byte* data, word32 data_len,
00389     byte* sig, word32 *sig_len,
00390     const void* key, word32 key_len, WC_RNG* rng)
00391 {
00392     int ret;
00393     word32 hash_len;
00394     byte *hash_data = NULL;
00395 
00396     /* Check arguments */
00397     if (data == NULL || data_len <= 0 ||
00398         sig == NULL || sig_len == NULL || *sig_len <= 0 ||
00399         key == NULL || key_len <= 0) {
00400         return BAD_FUNC_ARG;
00401     }
00402 
00403     /* Validate signature len (needs to be at least max) */
00404     if ((int)*sig_len < wc_SignatureGetSize(sig_type, key, key_len)) {
00405         WOLFSSL_MSG("wc_SignatureGenerate: Invalid sig type/len");
00406         return BAD_FUNC_ARG;
00407     }
00408 
00409     /* Validate hash size */
00410     ret = wc_HashGetDigestSize(hash_type);
00411     if (ret < 0) {
00412         WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len");
00413         return ret;
00414     }
00415     hash_len = ret;
00416 
00417     /* Allocate temporary buffer for hash data */
00418     hash_data = (byte*)XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00419     if (hash_data == NULL) {
00420         return MEMORY_E;
00421     }
00422 
00423     /* Perform hash of data */
00424     ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len);
00425     if (ret == 0) {
00426         /* Handle RSA with DER encoding */
00427         if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) {
00428         #if defined(NO_RSA) || defined(NO_ASN)
00429             ret = SIG_TYPE_E;
00430         #else
00431             ret = wc_SignatureDerEncode(hash_type, &hash_data, &hash_len);
00432         #endif
00433         }
00434 
00435         if (ret == 0) {
00436             /* Generate signature using hash */
00437             ret = wc_SignatureGenerateHash(hash_type, sig_type,
00438                 hash_data, hash_len, sig, sig_len, key, key_len, rng);
00439         }
00440     }
00441 
00442     if (hash_data) {
00443         XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00444     }
00445 
00446     return ret;
00447 }
00448 
00449 #endif /* NO_SIG_WRAPPER */
00450