diff --git a/configure.ac b/configure.ac index 62afc6e2..d88d7181 100644 --- a/configure.ac +++ b/configure.ac @@ -133,7 +133,7 @@ esac AX_CODE_COVERAGE() -AX_CHECK_COMPILE_FLAG([-Wunknown-warning-option], [have_unknown_warning_option="yes"], [have_unknown_warning_option="no"], [-Werror]) +AX_CHECK_COMPILE_FLAG([-Wunknown-warning-option], [have_unknown_warning_option="yes"], [have_unknown_warning_option="no"]) AM_CONDITIONAL([HAVE_UNKNOWN_WARNING_OPTION], [test "${have_unknown_warning_option}" = "yes"]) AC_ARG_ENABLE( diff --git a/src/libopensc/cwa14890.c b/src/libopensc/cwa14890.c index da471abf..88f68b85 100644 --- a/src/libopensc/cwa14890.c +++ b/src/libopensc/cwa14890.c @@ -519,8 +519,8 @@ static int cwa_internal_auth(sc_card_t * card, u8 * sig, size_t sig_len, u8 * da * @return SC_SUCCESS if ok; else errorcode */ static int cwa_prepare_external_auth(sc_card_t * card, - RSA * icc_pubkey, - RSA * ifd_privkey, + const RSA * icc_pubkey, + const RSA * ifd_privkey, u8 * sig, size_t sig_len) { @@ -594,7 +594,7 @@ static int cwa_prepare_external_auth(sc_card_t * card, buf3[127] = 0xBC; /* iso padding */ /* encrypt with ifd private key */ - len2 = RSA_private_decrypt(128, buf3, buf2, ifd_privkey, RSA_NO_PADDING); + len2 = RSA_private_decrypt(128, buf3, buf2, (RSA *)ifd_privkey, RSA_NO_PADDING); if (len2 < 0) { msg = "Prepare external auth: ifd_privk encrypt failed"; res = SC_ERROR_SM_ENCRYPT_FAILED; @@ -630,7 +630,7 @@ static int cwa_prepare_external_auth(sc_card_t * card, } /* re-encrypt result with icc public key */ - len1 = RSA_public_encrypt(len3, buf3, buf1, icc_pubkey, RSA_NO_PADDING); + len1 = RSA_public_encrypt(len3, buf3, buf1, (RSA *)icc_pubkey, RSA_NO_PADDING); if (len1 <= 0 || (size_t) len1 != sig_len) { msg = "Prepare external auth: icc_pubk encrypt failed"; res = SC_ERROR_SM_ENCRYPT_FAILED; @@ -842,8 +842,8 @@ static int cwa_compare_signature(u8 * data, size_t dlen, u8 * ifd_data) * @return SC_SUCCESS if ok; else error code */ static int cwa_verify_internal_auth(sc_card_t * card, - RSA * icc_pubkey, - RSA * ifd_privkey, + const RSA * icc_pubkey, + const RSA * ifd_privkey, u8 * ifdbuf, size_t ifdlen, u8 * sig, @@ -901,7 +901,7 @@ static int cwa_verify_internal_auth(sc_card_t * card, */ /* decrypt data with our ifd priv key */ - len1 = RSA_private_decrypt(sig_len, sig, buf1, ifd_privkey, RSA_NO_PADDING); + len1 = RSA_private_decrypt(sig_len, sig, buf1, (RSA *)ifd_privkey, RSA_NO_PADDING); if (len1 <= 0) { msg = "Verify Signature: decrypt with ifd privk failed"; res = SC_ERROR_SM_ENCRYPT_FAILED; @@ -911,7 +911,7 @@ static int cwa_verify_internal_auth(sc_card_t * card, /* OK: now we have SIGMIN in buf1 */ /* check if SIGMIN data matches SIG or N.ICC-SIG */ /* evaluate DS[SK.ICC.AUTH](SIG) trying to decrypt with icc pubk */ - len3 = RSA_public_encrypt(len1, buf1, buf3, icc_pubkey, RSA_NO_PADDING); + len3 = RSA_public_encrypt(len1, buf1, buf3, (RSA *) icc_pubkey, RSA_NO_PADDING); if (len3 <= 0) goto verify_nicc_sig; /* evaluate N.ICC-SIG and retry */ res = cwa_compare_signature(buf3, len3, ifdbuf); @@ -945,7 +945,7 @@ static int cwa_verify_internal_auth(sc_card_t * card, } /* ok: check again with new data */ /* evaluate DS[SK.ICC.AUTH](I.ICC-SIG) trying to decrypt with icc pubk */ - len3 = RSA_public_encrypt(len2, buf2, buf3, icc_pubkey, RSA_NO_PADDING); + len3 = RSA_public_encrypt(len2, buf2, buf3, (RSA *)icc_pubkey, RSA_NO_PADDING); if (len3 <= 0) { msg = "Verify Signature: cannot get valid SIG data"; res = SC_ERROR_INVALID_DATA; diff --git a/src/libopensc/p15card-helper.c b/src/libopensc/p15card-helper.c index e641858d..bf0ff901 100644 --- a/src/libopensc/p15card-helper.c +++ b/src/libopensc/p15card-helper.c @@ -143,7 +143,7 @@ CERT_HANDLE_FUNCTION(default_cert_handle) { int r; X509 *cert_data = NULL; EVP_PKEY *pkey = NULL; - RSA * rsa = NULL; + const RSA * rsa = NULL; int certtype = 0; int modulus_len = 0; const prdata* key = get_prkey_by_cert(items, cert); diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index 772179cd..c7d2d011 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -527,7 +527,9 @@ sc_pkcs15_prkey_attrs_from_cert(struct sc_pkcs15_card *p15card, struct sc_pkcs15 key_info = (struct sc_pkcs15_prkey_info *) key_object->data; +#if OPENSSL_VERSION_NUMBER < 0x30000000L ERR_load_ERR_strings(); +#endif ERR_load_crypto_strings(); sc_log(ctx, "CertValue(%"SC_FORMAT_LEN_SIZE_T"u) %p", diff --git a/src/libopensc/sc-ossl-compat.h b/src/libopensc/sc-ossl-compat.h index 339ad96c..ba4a0c51 100644 --- a/src/libopensc/sc-ossl-compat.h +++ b/src/libopensc/sc-ossl-compat.h @@ -273,6 +273,7 @@ static sc_ossl_inline void CRYPTO_secure_malloc_done() #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/pkcs11/openssl.c b/src/pkcs11/openssl.c index 92fed189..4c521e08 100644 --- a/src/pkcs11/openssl.c +++ b/src/pkcs11/openssl.c @@ -522,7 +522,7 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, unsigned int pubkey_len size_t signat_len_tmp; unsigned char *signat_tmp = NULL; EVP_PKEY_CTX *ctx; - EC_KEY *eckey; + const EC_KEY *eckey; int r; sc_log(context, "Trying to verify using EVP"); diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index b3528aaa..e77eb806 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -812,7 +812,7 @@ out: */ #define NUM_INTERFACES 2 #define DEFAULT_INTERFACE 0 -ck_interface interfaces[NUM_INTERFACES] = { +CK_INTERFACE interfaces[NUM_INTERFACES] = { {"PKCS 11", (void *)&pkcs11_function_list_3_0, 0}, {"PKCS 11", (void *)&pkcs11_function_list, 0} }; diff --git a/src/pkcs11/pkcs11-spy.c b/src/pkcs11/pkcs11-spy.c index c03418b3..b924bd74 100644 --- a/src/pkcs11/pkcs11-spy.c +++ b/src/pkcs11/pkcs11-spy.c @@ -176,7 +176,7 @@ allocate_function_list(int v3) /* The compatibility interfaces that can be returned from Interface functions * if the V3 API is used, but the proxied module does not support V3 API */ #define NUM_INTERFACES 1 -ck_interface compat_interfaces[NUM_INTERFACES] = { +CK_INTERFACE compat_interfaces[NUM_INTERFACES] = { {"PKCS 11", NULL, 0} }; diff --git a/src/pkcs11/pkcs11.h b/src/pkcs11/pkcs11.h index c400ac74..85aa98e0 100644 --- a/src/pkcs11/pkcs11.h +++ b/src/pkcs11/pkcs11.h @@ -63,9 +63,9 @@ extern "C" { version of this file, please consider deleting the revision macro (you may use a macro with a different name to keep track of your versions). */ -#define CRYPTOKI_VERSION_MAJOR 2 -#define CRYPTOKI_VERSION_MINOR 20 -#define CRYPTOKI_VERSION_REVISION 6 +#define CRYPTOKI_VERSION_MAJOR 3 +#define CRYPTOKI_VERSION_MINOR 0 +#define CRYPTOKI_VERSION_REVISION 0 /* Compatibility interface is default, unless CRYPTOKI_GNU is @@ -1786,6 +1786,8 @@ typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; #undef ck_rv_t #undef ck_notify_t +#undef ck_interface + #undef ck_function_list #undef ck_function_list_3_0 diff --git a/src/pkcs15init/pkcs15-oberthur-awp.c b/src/pkcs15init/pkcs15-oberthur-awp.c index b9991e78..70ff580d 100644 --- a/src/pkcs15init/pkcs15-oberthur-awp.c +++ b/src/pkcs15init/pkcs15-oberthur-awp.c @@ -769,7 +769,9 @@ awp_encode_key_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj int r = 0; LOG_FUNC_CALLED(ctx); +#if OPENSSL_VERSION_NUMBER < 0x30000000L ERR_load_ERR_strings(); +#endif ERR_load_crypto_strings(); key_info = (struct sc_pkcs15_prkey_info *)obj->data; @@ -827,7 +829,9 @@ awp_encode_key_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj sc_log(ctx, "cosm_encode_key_info() label:%s",ki->label.value); done: +#if OPENSSL_VERSION_NUMBER < 0x30000000L ERR_load_ERR_strings(); +#endif ERR_load_crypto_strings(); LOG_FUNC_RETURN(ctx, r); } @@ -933,7 +937,9 @@ awp_encode_cert_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *ob LOG_FUNC_CALLED(ctx); +#if OPENSSL_VERSION_NUMBER < 0x30000000L ERR_load_ERR_strings(); +#endif ERR_load_crypto_strings(); if (!obj || !ci) diff --git a/src/sm/sm-common.c b/src/sm/sm-common.c index ecd6ef12..d47228d8 100644 --- a/src/sm/sm-common.c +++ b/src/sm/sm-common.c @@ -40,6 +40,7 @@ #error "Need OpenSSL" #endif +#include #include #include @@ -49,6 +50,7 @@ #include "sm-common.h" +#if OPENSSL_VERSION_NUMBER < 0x30000000L /* * From crypto/des/des_locl.h of OpenSSL . */ @@ -120,18 +122,34 @@ DES_3cbc_encrypt(DES_cblock *input, DES_cblock *output, long length, } memcpy(*iv,icv_out,sizeof(DES_cblock)); } +#else +#include + +/* The single-DES algorithm is not available in the default provider anymore + * so we need to load the legacy provider. This is not done on the application + * start, but only as needed */ +OSSL_PROVIDER *legacy_provider = NULL; +#endif DES_LONG DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output, - long length, DES_key_schedule *schedule, DES_key_schedule *schedule2, + long length, unsigned char *key, const_DES_cblock *ivec) { - register DES_LONG tout0,tout1,tin0,tin1; register long l=length; - DES_LONG tin[2]; unsigned char *out = &(*output)[0]; const unsigned char *iv = &(*ivec)[0]; +#if OPENSSL_VERSION_NUMBER < 0x30000000L + register DES_LONG tout0,tout1,tin0,tin1; + DES_LONG tin[2]; + DES_cblock kk, k2; + DES_key_schedule ks,ks2; + + memcpy(&kk, key, 8); + memcpy(&k2, key + 8, 8); + DES_set_key_unchecked(&kk,&ks); + DES_set_key_unchecked(&k2,&ks2); c2l(iv,tout0); c2l(iv,tout1); @@ -147,7 +165,7 @@ DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output, tin0^=tout0; tin[0]=tin0; tin1^=tout1; tin[1]=tin1; - DES_encrypt1((DES_LONG *)tin,schedule, DES_ENCRYPT); + DES_encrypt1((DES_LONG *)tin, &ks, DES_ENCRYPT); tout0=tin[0]; tout1=tin[1]; } @@ -161,9 +179,8 @@ DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output, tin0^=tout0; tin[0]=tin0; tin1^=tout1; tin[1]=tin1; - DES_encrypt3((DES_LONG *)tin,schedule,schedule2,schedule); + DES_encrypt3((DES_LONG *)tin, &ks, &ks2, &ks); tout1=tin[1]; - if (out != NULL) { l2c(tout0,out); @@ -179,22 +196,87 @@ DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output, | ((tout1 << 8L) & 0x00FF0000) | ((tout1 << 24L) & 0xFF000000); return(tout1); +#else + EVP_CIPHER_CTX *cctx = NULL; + unsigned char outv[8], tmpout[4]; + int tmplen; + + /* Prepare IV */ + memcpy(outv, iv, sizeof outv); + + cctx = EVP_CIPHER_CTX_new(); + if (l > 8) { + if (legacy_provider == NULL) { + legacy_provider = OSSL_PROVIDER_load(NULL, "legacy"); + } + if (!EVP_EncryptInit_ex2(cctx, EVP_des_cbc(), key, iv, NULL)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + /* Disable padding, otherwise it will fail to decrypt non-padded inputs */ + EVP_CIPHER_CTX_set_padding(cctx, 0); + for (; l > 8; l -= 8, in += 8) { + if (!EVP_EncryptUpdate(cctx, outv, &tmplen, in, 8)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + } + if (!EVP_EncryptFinal_ex(cctx, outv + tmplen, &tmplen)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + } + + /* We need to return first 4 bytes from here */ + memcpy(tmpout, outv, 4); + if (!EVP_EncryptInit_ex2(cctx, EVP_des_ede_cbc(), key, outv, NULL)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + /* Disable padding, otherwise it will fail to decrypt non-padded inputs */ + EVP_CIPHER_CTX_set_padding(cctx, 0); + if (!EVP_EncryptUpdate(cctx, outv, &tmplen, in, l)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + if (!EVP_EncryptFinal_ex(cctx, outv + tmplen, &tmplen)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + if (out != NULL) { + memcpy(out, tmpout, 4); + memcpy(out+4, outv+4, 4); + } + EVP_CIPHER_CTX_free(cctx); + return ((outv[7] << 0L) & 0x000000FF) | + ((outv[6] << 8L) & 0x0000FF00) | + ((outv[5] << 16L) & 0x00FF0000) | + ((outv[4] << 24L) & 0xFF000000); +#endif } DES_LONG DES_cbc_cksum_3des(const unsigned char *in, DES_cblock *output, - long length, DES_key_schedule *schedule, DES_key_schedule *schedule2, + long length, unsigned char *key, const_DES_cblock *ivec) { - register DES_LONG tout0,tout1,tin0,tin1; register long l=length; - DES_LONG tin[2]; unsigned char *out = &(*output)[0]; const unsigned char *iv = &(*ivec)[0]; +#if OPENSSL_VERSION_NUMBER < 0x30000000L + register DES_LONG tout0,tout1,tin0,tin1; + DES_LONG tin[2]; + DES_cblock kk, k2; + DES_key_schedule ks,ks2; - c2l(iv,tout0); - c2l(iv,tout1); + memcpy(&kk, key, 8); + memcpy(&k2, key + 8, 8); + DES_set_key_unchecked(&kk,&ks); + DES_set_key_unchecked(&k2,&ks2); + + c2l(iv, tout0); + c2l(iv, tout1); for (; l>0; l-=8) { @@ -208,7 +290,7 @@ DES_cbc_cksum_3des(const unsigned char *in, DES_cblock *output, tin0^=tout0; tin[0]=tin0; tin1^=tout1; tin[1]=tin1; - DES_encrypt3((DES_LONG *)tin,schedule,schedule2,schedule); + DES_encrypt3((DES_LONG *)tin, &ks, &ks2, &ks); /* fix 15/10/91 eay - thanks to keithr@sco.COM */ tout0=tin[0]; tout1=tin[1]; @@ -228,6 +310,40 @@ DES_cbc_cksum_3des(const unsigned char *in, DES_cblock *output, | ((tout1 << 8L) & 0x00FF0000) | ((tout1 << 24L) & 0xFF000000); return(tout1); +#else + EVP_CIPHER_CTX *cctx = NULL; + unsigned char outv[8]; + int tmplen; + + /* Prepare IV */ + memcpy(outv, iv, sizeof outv); + + cctx = EVP_CIPHER_CTX_new(); + if (!EVP_EncryptInit_ex2(cctx, EVP_des_ede_cbc(), key, iv, NULL)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + /* Disable padding, otherwise it will fail to decrypt non-padded inputs */ + EVP_CIPHER_CTX_set_padding(cctx, 0); + for (; l > 0; l -= 8, in += 8) { + if (!EVP_EncryptUpdate(cctx, outv, &tmplen, in, 8)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + } + if (!EVP_EncryptFinal_ex(cctx, outv + tmplen, &tmplen)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + if (out != NULL) { + memcpy(out, outv, sizeof outv); + } + EVP_CIPHER_CTX_free(cctx); + return ((outv[7] << 0L) & 0x000000FF) | + ((outv[6] << 8L) & 0x0000FF00) | + ((outv[5] << 16L) & 0x00FF0000) | + ((outv[4] << 24L) & 0xFF000000); +#endif } @@ -235,9 +351,14 @@ int sm_encrypt_des_ecb3(unsigned char *key, unsigned char *data, int data_len, unsigned char **out, int *out_len) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L int ii; DES_cblock kk,k2; DES_key_schedule ks,ks2; +#else + EVP_CIPHER_CTX *cctx = NULL; + int tmplen; +#endif if (!out || !out_len) @@ -251,6 +372,7 @@ sm_encrypt_des_ecb3(unsigned char *key, unsigned char *data, int data_len, if (!(*out)) return -1; +#if OPENSSL_VERSION_NUMBER < 0x30000000L memcpy(&kk, key, 8); memcpy(&k2, key + 8, 8); @@ -260,6 +382,27 @@ sm_encrypt_des_ecb3(unsigned char *key, unsigned char *data, int data_len, for (ii=0; iikey.rsa = RSAPublicKey_dup(rsa)) == NULL) { + const RSA *rsa = EVP_PKEY_get0_RSA(evp); + if ((o->key.rsa = RSAPublicKey_dup((RSA *)rsa)) == NULL) { fail_msg("RSAPublicKey_dup failed"); return -1; } @@ -218,7 +219,7 @@ int callback_certificates(test_certs_t *objects, } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) { /* Extract public EC key */ - EC_KEY *ec = EVP_PKEY_get0_EC_KEY(evp); + const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(evp); if ((o->key.ec = EC_KEY_dup(ec)) == NULL) { fail_msg("EC_KEY_dup failed"); return -1; @@ -447,7 +448,6 @@ int callback_public_keys(test_certs_t *objects, if (strcmp((char *)curve->data, "edwards25519")) { debug_print(" [WARN %s ] Unknown curve name. " " expected edwards25519, got %s", o->id_str, curve->data); - return -1; } evp_type = EVP_PKEY_ED25519; break; @@ -455,7 +455,6 @@ int callback_public_keys(test_certs_t *objects, if (strcmp((char *)curve->data, "curve25519")) { debug_print(" [WARN %s ] Unknown curve name. " " expected curve25519, got %s", o->id_str, curve->data); - return -1; } evp_type = EVP_PKEY_X25519; break; @@ -466,12 +465,13 @@ int callback_public_keys(test_certs_t *objects, ASN1_PRINTABLESTRING_free(curve); } else if (d2i_ASN1_OBJECT(&obj, &a, (long)template[6].ulValueLen) != NULL) { int nid = OBJ_obj2nid(obj); + ASN1_OBJECT_free(obj); + switch (o->key_type) { case CKK_EC_EDWARDS: if (nid != NID_ED25519) { debug_print(" [WARN %s ] Unknown OID. " " expected NID_ED25519 (%d), got %d", o->id_str, NID_ED25519, nid); - return -1; } evp_type = EVP_PKEY_ED25519; break; @@ -479,7 +479,6 @@ int callback_public_keys(test_certs_t *objects, if (nid != NID_X25519) { debug_print(" [WARN %s ] Unknown OID. " " expected NID_X25519 (%d), got %d", o->id_str, NID_X25519, nid); - return -1; } evp_type = EVP_PKEY_X25519; break; @@ -487,7 +486,6 @@ int callback_public_keys(test_certs_t *objects, debug_print(" [WARN %s ] Unknown key type %lu", o->id_str, o->key_type); return -1; } - ASN1_OBJECT_free(obj); } else { debug_print(" [WARN %s ] Failed to convert EC_PARAMS" " to curve name or object id", o->id_str); @@ -780,8 +778,12 @@ const char *get_mechanism_name(int mech_id) return "ECDH1_COFACTOR_DERIVE"; case CKM_EC_KEY_PAIR_GEN: return "EC_KEY_PAIR_GEN"; + case CKM_EC_EDWARDS_KEY_PAIR_GEN: + return "EC_EDWARDS_KEY_PAIR_GEN"; case CKM_RSA_PKCS_KEY_PAIR_GEN: return "RSA_PKCS_KEY_PAIR_GEN"; + case CKM_GENERIC_SECRET_KEY_GEN: + return "GENERIC_SECRET_KEY_GEN"; case CKM_MD5_RSA_PKCS: return "MD5_RSA_PKCS"; case CKM_RIPEMD160_RSA_PKCS: @@ -802,6 +804,8 @@ const char *get_mechanism_name(int mech_id) return "MD5_HMAC"; case CKM_SHA_1_HMAC: return "SHA_1_HMAC"; + case CKM_SHA224_HMAC: + return "SHA224_HMAC"; case CKM_SHA256_HMAC: return "SHA256_HMAC"; case CKM_SHA384_HMAC: diff --git a/src/tests/p11test/p11test_case_readonly.c b/src/tests/p11test/p11test_case_readonly.c index df39ecb4..60ad0407 100644 --- a/src/tests/p11test/p11test_case_readonly.c +++ b/src/tests/p11test/p11test_case_readonly.c @@ -498,9 +498,7 @@ int verify_message(test_cert_t *o, token_info_t *info, CK_BYTE *message, CK_FUNCTION_LIST_PTR fp = info->function_pointer; CK_MECHANISM sign_mechanism = { mech->mech, NULL_PTR, 0 }; static int verify_support = 1; -#ifndef NDEBUG char *name; -#endif if (!verify_support) goto openssl_verify; @@ -531,15 +529,11 @@ int verify_message(test_cert_t *o, token_info_t *info, CK_BYTE *message, /* Final */ rv = fp->C_VerifyFinal(info->session_handle, sign, sign_length); -#ifndef NDEBUG name = "C_VerifyFinal"; -#endif } else { rv = fp->C_Verify(info->session_handle, message, message_length, sign, sign_length); -#ifndef NDEBUG name = "C_Verify"; -#endif } if (rv == CKR_OK) { mech->result_flags |= FLAGS_SIGN; diff --git a/src/tests/p11test/p11test_common.h b/src/tests/p11test/p11test_common.h index 1122e8e3..d3eb1040 100644 --- a/src/tests/p11test/p11test_common.h +++ b/src/tests/p11test/p11test_common.h @@ -33,12 +33,12 @@ #define MAX_MECHS 200 -#ifndef NDEBUG - #define debug_print(fmt, ...) \ - { fprintf(stderr, fmt "\n", ##__VA_ARGS__); } while (0) -#else - #define debug_print(fmt, ...) -#endif +#define debug_print(fmt, ...) \ + do { \ + if (debug_flag) { \ + fprintf(stderr, fmt "\n", ##__VA_ARGS__); \ + } \ + } while (0) #define FLAGS_SIGN 0x01 #define FLAGS_SIGN_OPENSSL 0x02 @@ -89,6 +89,7 @@ typedef struct { } token_info_t; extern token_info_t token; +extern int debug_flag; #endif /* P11TEST_COMMON_H */ diff --git a/src/tests/unittests/Makefile.am b/src/tests/unittests/Makefile.am index b6bef298..03019c32 100644 --- a/src/tests/unittests/Makefile.am +++ b/src/tests/unittests/Makefile.am @@ -32,6 +32,13 @@ compression_SOURCES = compression.c compression_LDADD = $(LDADD) $(OPTIONAL_ZLIB_LIBS) endif +if ENABLE_OPENSSL +noinst_PROGRAMS += sm +TESTS += sm + +sm_SOURCES = sm.c +sm_LDADD = $(top_builddir)/src/sm/libsm.la $(LDADD) +endif endif diff --git a/src/tests/unittests/asn1.c b/src/tests/unittests/asn1.c index 5f5d4ea3..799722cc 100644 --- a/src/tests/unittests/asn1.c +++ b/src/tests/unittests/asn1.c @@ -241,7 +241,7 @@ static int setup_sc_context(void **state) sc_context_t *ctx = NULL; int rv; - rv = sc_establish_context(&ctx, "fuzz"); + rv = sc_establish_context(&ctx, "asn1"); assert_non_null(ctx); assert_int_equal(rv, SC_SUCCESS); diff --git a/src/tests/unittests/sm.c b/src/tests/unittests/sm.c new file mode 100644 index 00000000..ab6e819e --- /dev/null +++ b/src/tests/unittests/sm.c @@ -0,0 +1,376 @@ +/* + * sm.c: Unit tests for Secure Messaging + * + * Copyright (C) 2021 Red Hat, Inc. + * + * Author: Jakub Jelen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "torture.h" +#include "libopensc/log.c" +#include "sm/sm-common.h" + +/* Setup context */ +static int setup_sc_context(void **state) +{ + sc_context_t *ctx = NULL; + int rv; + + rv = sc_establish_context(&ctx, "sm"); + assert_non_null(ctx); + assert_int_equal(rv, SC_SUCCESS); + + *state = ctx; + + return 0; +} + +/* Cleanup context */ +static int teardown_sc_context(void **state) +{ + sc_context_t *ctx = *state; + int rv; + + rv = sc_release_context(ctx); + assert_int_equal(rv, SC_SUCCESS); + + return 0; +} + +static void torture_sm_incr_ssc(void **state) +{ + unsigned char in[] = {0x00, 0x00}; + + (void)state; + + /* just make sure it does not crash */ + sm_incr_ssc(NULL, 0); + + /* zero-length input should not underflow the buffer */ + sm_incr_ssc(in, 0); + + /* shortest possible input */ + in[0] = 0x42; + sm_incr_ssc(in, 1); + assert_int_equal(in[0], 0x43); + + /* overflow to the second byte */ + in[0] = 0x00; + in[1] = 0xff; + sm_incr_ssc(in, 2); + assert_int_equal(in[0], 0x01); + assert_int_equal(in[1], 0x00); + + /* overflow */ + in[0] = 0xff; + in[1] = 0xff; + sm_incr_ssc(in, 2); + assert_int_equal(in[0], 0x00); + assert_int_equal(in[1], 0x00); +} + +static void torture_sm_crypt_des_cbc3(void **state) +{ + sc_context_t *ctx = *state; + /* Test vector from + * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-20.pdf + * 5.2.1.1 The Variable Plaintext Known Answer Test -TCBC Mode + */ + unsigned char key[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */}; + unsigned char plain[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned char ciphertext[] = {0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00}; + unsigned char *out = NULL; /* allocates */ + size_t out_len = 0; + int rv; + + rv = sm_encrypt_des_cbc3(ctx, key, plain, sizeof(plain), &out, &out_len, 1); + assert_int_equal(rv, SC_SUCCESS); + assert_int_equal(out_len, sizeof(ciphertext)); + assert_memory_equal(out, ciphertext, sizeof(ciphertext)); + free(out); + out = NULL; + out_len = 0; + + rv = sm_decrypt_des_cbc3(ctx, key, ciphertext, sizeof(ciphertext), &out, &out_len); + assert_int_equal(rv, SC_SUCCESS); + assert_memory_equal(out, plain, sizeof(plain)); + free(out); +} + +static void torture_sm_crypt_des_cbc3_multiblock(void **state) +{ + /* not a test vector -- generated by openssl 1.1.1 */ + sc_context_t *ctx = *state; + unsigned char key[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */}; + unsigned char plain[] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00}; + unsigned char ciphertext[] = { + 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00, + 0xAF, 0xA0, 0x77, 0x1d, 0x35, 0xE1, 0xCC, 0x26}; + unsigned char *out = NULL; /* allocates */ + size_t out_len = 0; + int rv; + + rv = sm_encrypt_des_cbc3(ctx, key, plain, sizeof(plain), &out, &out_len, 1); + assert_int_equal(rv, SC_SUCCESS); + assert_int_equal(out_len, sizeof(ciphertext)); + assert_memory_equal(out, ciphertext, sizeof(ciphertext)); + free(out); + out = NULL; + out_len = 0; + + rv = sm_decrypt_des_cbc3(ctx, key, ciphertext, sizeof(ciphertext), &out, &out_len); + assert_int_equal(rv, SC_SUCCESS); + assert_memory_equal(out, plain, sizeof(plain)); + free(out); +} + +static void torture_sm_crypt_des_cbc3_force_pad(void **state) +{ + /* not a test vector -- generated by openssl 1.1.1 */ + sc_context_t *ctx = *state; + unsigned char key[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */}; + unsigned char plain[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned char ciphertext[] = { + 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00, + 0xC6, 0xD3, 0xE1, 0x4F, 0xFB, 0xDE, 0xDF, 0xF9}; + unsigned char *out = NULL; /* allocates */ + size_t out_len = 0; + int rv; + + rv = sm_encrypt_des_cbc3(ctx, key, plain, sizeof(plain), &out, &out_len, 0); + assert_int_equal(rv, SC_SUCCESS); + assert_int_equal(out_len, sizeof(ciphertext)); + assert_memory_equal(out, ciphertext, sizeof(ciphertext)); + free(out); + out = NULL; + out_len = 0; + + rv = sm_decrypt_des_cbc3(ctx, key, ciphertext, sizeof(ciphertext), &out, &out_len); + assert_int_equal(rv, SC_SUCCESS); + assert_memory_equal(out, plain, sizeof(plain)); + free(out); +} + +static void torture_sm_encrypt_des_ecb3(void **state) +{ + /* Test vector from + * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-20.pdf + * 5.2.1.1 The Variable Plaintext Known Answer Test -TCBC Mode + */ + unsigned char key[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */}; + unsigned char plain[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned char ciphertext[] = {0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00}; + unsigned char *out = NULL; /* allocates */ + int out_len = 0; + int rv; + + (void)state; + + rv = sm_encrypt_des_ecb3(key, plain, sizeof(plain), &out, &out_len); + assert_int_equal(rv, SC_SUCCESS); + assert_int_equal(out_len, sizeof(ciphertext)); + assert_memory_equal(out, ciphertext, sizeof(ciphertext)); + free(out); + out = NULL; + out_len = 0; + + rv = sm_encrypt_des_ecb3(key, ciphertext, sizeof(ciphertext), &out, &out_len); + assert_int_equal(rv, SC_SUCCESS); + assert_memory_equal(out, plain, sizeof(plain)); + free(out); +} + +static void torture_sm_encrypt_des_ecb3_multiblock(void **state) +{ + /* not a test vector -- generated by openssl 1.1.1 */ + unsigned char key[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */}; + unsigned char plain[] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned char ciphertext[] = { + 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00, + 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F}; + unsigned char *out = NULL; /* allocates */ + int out_len = 0; + int rv; + + (void)state; + + rv = sm_encrypt_des_ecb3(key, plain, sizeof(plain), &out, &out_len); + assert_int_equal(rv, SC_SUCCESS); + assert_int_equal(out_len, sizeof(ciphertext)); + assert_memory_equal(out, ciphertext, sizeof(ciphertext)); + free(out); + out = NULL; + out_len = 0; + + rv = sm_encrypt_des_ecb3(key, ciphertext, sizeof(ciphertext), &out, &out_len); + assert_int_equal(rv, SC_SUCCESS); + assert_memory_equal(out, plain, sizeof(plain)); + free(out); +} + +static void torture_DES_cbc_cksum_3des(void **state) +{ + /* not a test vector -- generated by openssl 1.1.1 */ + unsigned char key[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */}; + unsigned char iv[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned char plain[] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned char checksum_ref[] = { + 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00}; + unsigned long sum_ref = 0xdd31d900UL; + unsigned char checksum[8]; + unsigned long sum; + + (void)state; + + sum = DES_cbc_cksum_3des(plain, &checksum, sizeof(plain), key, &iv); + assert_int_equal(sum, sum_ref); + assert_memory_equal(checksum, checksum_ref, sizeof(checksum_ref)); + + /* The checksum argument is not required */ + sum = DES_cbc_cksum_3des(plain, NULL, sizeof(plain), key, &iv); + assert_int_equal(sum, sum_ref); +} + +static void torture_DES_cbc_cksum_3des_multiblock(void **state) +{ + /* not a test vector -- generated by openssl 1.1.1 */ + unsigned char key[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */}; + unsigned char iv[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + /* I think this function assumes/requires full blocks */ + unsigned char plain[] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned char checksum_ref[] = { + 0xC6, 0x3F, 0x6E, 0x72, 0xC7, 0xCF, 0x4E, 0x07}; + unsigned long sum_ref = 0xc7cf4e07UL; + unsigned char checksum[8]; + unsigned long sum; + + (void)state; + + sum = DES_cbc_cksum_3des(plain, &checksum, sizeof(plain), key, &iv); + assert_memory_equal(checksum, checksum_ref, sizeof(checksum_ref)); + assert_int_equal(sum, sum_ref); + + /* The checksum argument is not required */ + sum = DES_cbc_cksum_3des(plain, NULL, sizeof(plain), key, &iv); + assert_int_equal(sum, sum_ref); +} + +static void torture_DES_cbc_cksum_3des_emv96(void **state) +{ + /* not a test vector -- generated by openssl 1.1.1 */ + unsigned char key[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */}; + unsigned char iv[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned char plain[] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned char checksum_ref[] = { + 0x00, 0x00, 0x00, 0x00, 0xDD, 0x31, 0xD9, 0x00}; + unsigned long sum_ref = 0xdd31d900UL; + unsigned char checksum[8]; + unsigned long sum; + + (void)state; + + sum = DES_cbc_cksum_3des_emv96(plain, &checksum, sizeof(plain), key, &iv); + assert_int_equal(sum, sum_ref); + assert_memory_equal(checksum, checksum_ref, sizeof(checksum_ref)); + + /* The checksum argument is not required */ + sum = DES_cbc_cksum_3des_emv96(plain, NULL, sizeof(plain), key, &iv); + assert_int_equal(sum, sum_ref); +} + +static void torture_DES_cbc_cksum_3des_emv96_multiblock(void **state) +{ + /* not a test vector -- generated by openssl 1.1.1 */ + unsigned char key[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */}; + unsigned char iv[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + /* I think this function assumes/requires full blocks */ + unsigned char plain[] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned char checksum_ref[] = { + 0x95, 0xf8, 0xA5, 0xe5, 0xC7, 0xCF, 0x4E, 0x07}; + unsigned long sum_ref = 0xc7cf4e07UL; + unsigned char checksum[8] = {0}; + unsigned long sum; + + (void)state; + + sum = DES_cbc_cksum_3des_emv96(plain, &checksum, sizeof(plain), key, &iv); + assert_memory_equal(checksum, checksum_ref, sizeof(checksum_ref)); + assert_int_equal(sum, sum_ref); + + /* The checksum argument is not required */ + sum = DES_cbc_cksum_3des_emv96(plain, NULL, sizeof(plain), key, &iv); + assert_int_equal(sum, sum_ref); +} + +int main(void) +{ + int rc; + struct CMUnitTest tests[] = { + /* sm_incr_ssc */ + cmocka_unit_test(torture_sm_incr_ssc), + /* sm_encrypt_des_cbc3 and sm_decrypt_des_cbc3 */ + cmocka_unit_test_setup_teardown(torture_sm_crypt_des_cbc3, + setup_sc_context, teardown_sc_context), + cmocka_unit_test_setup_teardown(torture_sm_crypt_des_cbc3_multiblock, + setup_sc_context, teardown_sc_context), + cmocka_unit_test_setup_teardown(torture_sm_crypt_des_cbc3_force_pad, + setup_sc_context, teardown_sc_context), + /* sm_encrypt_des_ecb3 */ + cmocka_unit_test(torture_sm_encrypt_des_ecb3), + cmocka_unit_test(torture_sm_encrypt_des_ecb3_multiblock), + /* DES_cbc_cksum_3des */ + cmocka_unit_test(torture_DES_cbc_cksum_3des), + cmocka_unit_test(torture_DES_cbc_cksum_3des_multiblock), + /* DES_cbc_cksum_3des_emv96 */ + cmocka_unit_test(torture_DES_cbc_cksum_3des_emv96), + cmocka_unit_test(torture_DES_cbc_cksum_3des_emv96_multiblock), + }; + + rc = cmocka_run_group_tests(tests, NULL, NULL); + return rc; +}