/* ToDo: problems with RSA_PKCS1_OAEP_PADDING -> find solution */ OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_Public_Verify( OpcUa_CryptoProvider* a_pProvider, OpcUa_ByteString a_data, OpcUa_Key* a_publicKey, OpcUa_Int16 a_padding, OpcUa_ByteString* a_pSignature) { EVP_PKEY* pPublicKey = OpcUa_Null; OpcUa_Int32 keySize = 0; const unsigned char *pData; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_Public_Verify"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReferenceParameter(a_padding); OpcUa_ReturnErrorIfArgumentNull(a_data.Data); OpcUa_ReturnErrorIfArgumentNull(a_publicKey); OpcUa_ReturnErrorIfArgumentNull(a_publicKey->Key.Data); OpcUa_ReturnErrorIfArgumentNull(a_pSignature); if(a_publicKey->Type != OpcUa_Crypto_KeyType_Rsa_Public) { OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument); } pData = a_publicKey->Key.Data; pPublicKey = d2i_PublicKey(EVP_PKEY_RSA,OpcUa_Null, &pData, a_publicKey->Key.Length); if(pPublicKey == OpcUa_Null) { OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument); } keySize = RSA_size(pPublicKey->pkey.rsa); if((a_pSignature->Length%keySize) != 0) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } if (RSA_verify(NID_sha1, a_data.Data, a_data.Length, a_pSignature->Data, a_pSignature->Length, pPublicKey->pkey.rsa) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } EVP_PKEY_free(pPublicKey); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if (pPublicKey != OpcUa_Null) { EVP_PKEY_free(pPublicKey); } OpcUa_FinishErrorHandling; }
EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) { EVP_PKEY *ret=NULL; long j; int type; unsigned char *p; #ifndef OPENSSL_NO_DSA const unsigned char *cp; X509_ALGOR *a; #endif if (key == NULL) goto err; if (key->pkey != NULL) { CRYPTO_add(&key->pkey->references,1,CRYPTO_LOCK_EVP_PKEY); return(key->pkey); } if (key->public_key == NULL) goto err; type=OBJ_obj2nid(key->algor->algorithm); p=key->public_key->data; j=key->public_key->length; if ((ret=d2i_PublicKey(type,NULL,&p,(long)j)) == NULL) { X509err(X509_F_X509_PUBKEY_GET,X509_R_ERR_ASN1_LIB); goto err; } ret->save_parameters=0; #ifndef OPENSSL_NO_DSA a=key->algor; if (ret->type == EVP_PKEY_DSA) { if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE)) { ret->pkey.dsa->write_params=0; cp=p=a->parameter->value.sequence->data; j=a->parameter->value.sequence->length; if (!d2i_DSAparams(&ret->pkey.dsa,&cp,(long)j)) goto err; } ret->save_parameters=1; } #endif key->pkey=ret; CRYPTO_add(&ret->references,1,CRYPTO_LOCK_EVP_PKEY); return(ret); err: if (ret != NULL) EVP_PKEY_free(ret); return(NULL); }
void pki_key::d2i_old(QByteArray &ba, int type) { if (key) EVP_PKEY_free(key); const unsigned char *p, *p1; p = p1 = (const unsigned char *)ba.constData(); key = d2i_PublicKey(type, NULL, &p1, ba.count()); ba = ba.mid(p1-p); pki_openssl_error(); }
EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) { EVP_PKEY *ret=NULL; long j; int type; const unsigned char *p; if (key == NULL) goto err; if (key->pkey != NULL) { CRYPTO_add(&key->pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); return(key->pkey); } if (key->public_key == NULL) goto err; type=OBJ_obj2nid(key->algor->algorithm); if ((ret = EVP_PKEY_new()) == NULL) { //X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE);//samyang modify goto err; } ret->type = EVP_PKEY_type(type); #if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA) //a=key->algor; #endif p=key->public_key->data; j=key->public_key->length; if (!d2i_PublicKey(type, &ret, &p, (long)j)) { //X509err(X509_F_X509_PUBKEY_GET, X509_R_ERR_ASN1_LIB);//samyang modify goto err; } key->pkey = ret; CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY); return(ret); err: if (ret != NULL) EVP_PKEY_free(ret); return(NULL); }
/*===========================================================================* OpcUa_P_OpenSSL_RSA_Public_GetKeyLength *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_Public_GetKeyLength( OpcUa_CryptoProvider* a_pProvider, OpcUa_Key a_publicKey, OpcUa_UInt32* a_pKeyLen) { EVP_PKEY* pPublicKey = OpcUa_Null; const unsigned char *pData; OpcUa_UInt32 uKeySize = 0; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_Public_GetKeyLength"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_publicKey.Key.Data); OpcUa_ReturnErrorIfArgumentNull(a_pKeyLen); *a_pKeyLen = 0; if(a_publicKey.Type != OpcUa_Crypto_KeyType_Rsa_Public) { OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument); } pData = a_publicKey.Key.Data; pPublicKey = d2i_PublicKey(EVP_PKEY_RSA, OpcUa_Null, &pData, a_publicKey.Key.Length); uKeySize = RSA_size(pPublicKey->pkey.rsa); *a_pKeyLen = uKeySize*8; EVP_PKEY_free(pPublicKey); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pPublicKey != OpcUa_Null) { EVP_PKEY_free(pPublicKey); } *a_pKeyLen = (OpcUa_UInt32)-1; OpcUa_FinishErrorHandling; }
/*===========================================================================* OpcUa_P_OpenSSL_RSA_Public_Encrypt *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_Public_Encrypt( OpcUa_CryptoProvider* a_pProvider, OpcUa_Byte* a_pPlainText, OpcUa_UInt32 a_plainTextLen, OpcUa_Key* a_publicKey, OpcUa_Int16 a_padding, OpcUa_Byte* a_pCipherText, OpcUa_UInt32* a_pCipherTextLen) { EVP_PKEY* pPublicKey = OpcUa_Null; OpcUa_UInt32 uKeySize = 0; OpcUa_UInt32 uEncryptedDataSize = 0; OpcUa_UInt32 uPlainTextPosition = 0; OpcUa_UInt32 uCipherTextPosition = 0; OpcUa_UInt32 uBytesToEncrypt = 0; OpcUa_Int32 iEncryptedBytes = 0; const unsigned char *pData; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_Public_Encrypt"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_publicKey); OpcUa_ReturnErrorIfArgumentNull(a_publicKey->Key.Data); OpcUa_ReturnErrorIfArgumentNull(a_pCipherTextLen); *a_pCipherTextLen = 0; if((OpcUa_Int32)a_plainTextLen < 1) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } if(a_publicKey->Type != OpcUa_Crypto_KeyType_Rsa_Public) { OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument); } pData = a_publicKey->Key.Data; pPublicKey = d2i_PublicKey(EVP_PKEY_RSA, OpcUa_Null, &pData, a_publicKey->Key.Length); if ( pPublicKey != OpcUa_Null ) { uKeySize = RSA_size(pPublicKey->pkey.rsa); } else { OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument); } /* check padding type */ switch(a_padding) { case RSA_PKCS1_PADDING: { uEncryptedDataSize = uKeySize - 11; break; } case RSA_PKCS1_OAEP_PADDING: { uEncryptedDataSize = uKeySize - 42; break; } case RSA_NO_PADDING: { uEncryptedDataSize = uKeySize; break; } default: { OpcUa_GotoErrorWithStatus(OpcUa_BadNotSupported); } } if(a_plainTextLen < uEncryptedDataSize) { uBytesToEncrypt = a_plainTextLen; } else { uBytesToEncrypt = uEncryptedDataSize; } while(uPlainTextPosition < a_plainTextLen) { /* the last part could be smaller */ if((a_plainTextLen >= uEncryptedDataSize) && ((a_plainTextLen - uPlainTextPosition) < uEncryptedDataSize)) { uBytesToEncrypt = a_plainTextLen - uPlainTextPosition; } if((a_pCipherText != OpcUa_Null) && (a_pPlainText != OpcUa_Null)) { iEncryptedBytes = RSA_public_encrypt( uBytesToEncrypt, /* how much to encrypt */ a_pPlainText + uPlainTextPosition, /* what to encrypt */ a_pCipherText + uCipherTextPosition,/* where to encrypt */ pPublicKey->pkey.rsa, /* public key */ a_padding); /* padding mode */ if(iEncryptedBytes < 0) { const char* sError = OpcUa_Null; unsigned long error = 0; error = ERR_get_error(); ERR_load_crypto_strings(); sError = ERR_reason_error_string(error); sError = ERR_func_error_string(error); sError = ERR_lib_error_string(error); uStatus = OpcUa_Bad; OpcUa_GotoError; } } else { iEncryptedBytes = uKeySize; } *a_pCipherTextLen = *a_pCipherTextLen + iEncryptedBytes; uCipherTextPosition += uKeySize; uPlainTextPosition += uBytesToEncrypt; } EVP_PKEY_free(pPublicKey); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pPublicKey != OpcUa_Null) { EVP_PKEY_free(pPublicKey); } *a_pCipherTextLen = (OpcUa_UInt32)-1; OpcUa_FinishErrorHandling; }
EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) { EVP_PKEY *ret=NULL; long j; int type; const unsigned char *p; #if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA) const unsigned char *cp; X509_ALGOR *a; #endif if (key == NULL) goto err; if (key->pkey != NULL) { CRYPTO_add(&key->pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); return(key->pkey); } if (key->public_key == NULL) goto err; type=OBJ_obj2nid(key->algor->algorithm); if ((ret = EVP_PKEY_new()) == NULL) { X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE); goto err; } ret->type = EVP_PKEY_type(type); /* the parameters must be extracted before the public key (ECDSA!) */ #if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA) a=key->algor; #endif if (0) ; #ifndef OPENSSL_NO_DSA else if (ret->type == EVP_PKEY_DSA) { if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE)) { if ((ret->pkey.dsa = DSA_new()) == NULL) { X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE); goto err; } ret->pkey.dsa->write_params=0; cp=p=a->parameter->value.sequence->data; j=a->parameter->value.sequence->length; if (!d2i_DSAparams(&ret->pkey.dsa, &cp, (long)j)) goto err; } ret->save_parameters=1; } #endif #ifndef OPENSSL_NO_EC else if (ret->type == EVP_PKEY_EC) { if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE)) { /* type == V_ASN1_SEQUENCE => we have explicit parameters * (e.g. parameters in the X9_62_EC_PARAMETERS-structure ) */ if ((ret->pkey.ec= EC_KEY_new()) == NULL) { X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE); goto err; } cp = p = a->parameter->value.sequence->data; j = a->parameter->value.sequence->length; if (!d2i_ECParameters(&ret->pkey.ec, &cp, (long)j)) { X509err(X509_F_X509_PUBKEY_GET, ERR_R_EC_LIB); goto err; } } else if (a->parameter && (a->parameter->type == V_ASN1_OBJECT)) { /* type == V_ASN1_OBJECT => the parameters are given * by an asn1 OID */ EC_KEY *ec_key; EC_GROUP *group; if (ret->pkey.ec == NULL) ret->pkey.ec = EC_KEY_new(); ec_key = ret->pkey.ec; if (ec_key == NULL) goto err; group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(a->parameter->value.object)); if (group == NULL) goto err; EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); if (EC_KEY_set_group(ec_key, group) == 0) goto err; EC_GROUP_free(group); } /* the case implicitlyCA is currently not implemented */ ret->save_parameters = 1; } #endif p=key->public_key->data; j=key->public_key->length; if (!d2i_PublicKey(type, &ret, &p, (long)j)) { X509err(X509_F_X509_PUBKEY_GET, X509_R_ERR_ASN1_LIB); goto err; } key->pkey = ret; CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY); return(ret); err: if (ret != NULL) EVP_PKEY_free(ret); return(NULL); }
/* If no hash function was used, finish with RSA_public_decrypt(). * If a hash function was used, we can make a big shortcut by * finishing with EVP_VerifyFinal(). */ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len, const unsigned char *pubkey_params, int pubkey_params_len, CK_MECHANISM_TYPE mech, sc_pkcs11_operation_t *md, unsigned char *data, int data_len, unsigned char *signat, int signat_len) { int res; CK_RV rv = CKR_GENERAL_ERROR; EVP_PKEY *pkey; if (mech == CKM_GOSTR3410) { #if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC) return gostr3410_verify_data(pubkey, pubkey_len, pubkey_params, pubkey_params_len, data, data_len, signat, signat_len); #else (void)pubkey_params, (void)pubkey_params_len; /* no warning */ return CKR_FUNCTION_NOT_SUPPORTED; #endif } pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &pubkey, pubkey_len); if (pkey == NULL) return CKR_GENERAL_ERROR; if (md != NULL) { EVP_MD_CTX *md_ctx = DIGEST_CTX(md); res = EVP_VerifyFinal(md_ctx, signat, signat_len, pkey); EVP_PKEY_free(pkey); if (res == 1) return CKR_OK; else if (res == 0) return CKR_SIGNATURE_INVALID; else { sc_debug(context, SC_LOG_DEBUG_NORMAL, "EVP_VerifyFinal() returned %d\n", res); return CKR_GENERAL_ERROR; } } else { RSA *rsa; unsigned char *rsa_out = NULL, pad; int rsa_outlen = 0; switch(mech) { case CKM_RSA_PKCS: pad = RSA_PKCS1_PADDING; break; case CKM_RSA_X_509: pad = RSA_NO_PADDING; break; default: EVP_PKEY_free(pkey); return CKR_ARGUMENTS_BAD; } rsa = EVP_PKEY_get1_RSA(pkey); EVP_PKEY_free(pkey); if (rsa == NULL) return CKR_DEVICE_MEMORY; rsa_out = malloc(RSA_size(rsa)); if (rsa_out == NULL) { RSA_free(rsa); return CKR_DEVICE_MEMORY; } rsa_outlen = RSA_public_decrypt(signat_len, signat, rsa_out, rsa, pad); RSA_free(rsa); if(rsa_outlen <= 0) { free(rsa_out); sc_debug(context, SC_LOG_DEBUG_NORMAL, "RSA_public_decrypt() returned %d\n", rsa_outlen); return CKR_GENERAL_ERROR; } if (rsa_outlen == data_len && memcmp(rsa_out, data, data_len) == 0) rv = CKR_OK; else rv = CKR_SIGNATURE_INVALID; free(rsa_out); } return rv; }
static EVP_PKEY* unwrap_key(const uint8_t* keyBlob, const size_t keyBlobLength) { long publicLen = 0; long privateLen = 0; const uint8_t* p = keyBlob; const uint8_t *const end = keyBlob + keyBlobLength; if (keyBlob == NULL) { ALOGE("supplied key blob was NULL"); return NULL; } // Should be large enough for: // int32 magic, int32 type, int32 pubLen, char* pub, int32 privLen, char* priv if (keyBlobLength < (get_softkey_header_size() + sizeof(int) + sizeof(int) + 1 + sizeof(int) + 1)) { ALOGE("key blob appears to be truncated"); return NULL; } if (!is_softkey(p, keyBlobLength)) { ALOGE("cannot read key; it was not made by this keymaster"); return NULL; } p += get_softkey_header_size(); int type = 0; for (size_t i = 0; i < sizeof(int); i++) { type = (type << 8) | *p++; } Unique_EVP_PKEY pkey(EVP_PKEY_new()); if (pkey.get() == NULL) { logOpenSSLError("unwrap_key"); return NULL; } for (size_t i = 0; i < sizeof(int); i++) { publicLen = (publicLen << 8) | *p++; } if (p + publicLen > end) { ALOGE("public key length encoding error: size=%ld, end=%d", publicLen, end - p); return NULL; } EVP_PKEY* tmp = pkey.get(); d2i_PublicKey(type, &tmp, &p, publicLen); if (end - p < 2) { ALOGE("private key truncated"); return NULL; } for (size_t i = 0; i < sizeof(int); i++) { privateLen = (privateLen << 8) | *p++; } if (p + privateLen > end) { ALOGE("private key length encoding error: size=%ld, end=%d", privateLen, end - p); return NULL; } d2i_PrivateKey(type, &tmp, &p, privateLen); return pkey.release(); }
RTDECL(int) RTCrPkixPubKeyVerifySignature(PCRTASN1OBJID pAlgorithm, PCRTASN1DYNTYPE pParameters, PCRTASN1BITSTRING pPublicKey, PCRTASN1BITSTRING pSignatureValue, const void *pvData, size_t cbData, PRTERRINFO pErrInfo) { /* * Valid input. */ AssertPtrReturn(pAlgorithm, VERR_INVALID_POINTER); AssertReturn(RTAsn1ObjId_IsPresent(pAlgorithm), VERR_INVALID_POINTER); if (pParameters) { AssertPtrReturn(pParameters, VERR_INVALID_POINTER); if (pParameters->enmType == RTASN1TYPE_NULL) pParameters = NULL; } AssertPtrReturn(pPublicKey, VERR_INVALID_POINTER); AssertReturn(RTAsn1BitString_IsPresent(pPublicKey), VERR_INVALID_POINTER); AssertPtrReturn(pSignatureValue, VERR_INVALID_POINTER); AssertReturn(RTAsn1BitString_IsPresent(pSignatureValue), VERR_INVALID_POINTER); AssertPtrReturn(pvData, VERR_INVALID_POINTER); AssertReturn(cbData > 0, VERR_INVALID_PARAMETER); /* * Parameters are not currently supported (openssl code path). */ if (pParameters) return RTErrInfoSet(pErrInfo, VERR_CR_PKIX_CIPHER_ALGO_PARAMS_NOT_IMPL, "Cipher algorithm parameters are not yet supported."); /* * Validate using IPRT. */ RTCRPKIXSIGNATURE hSignature; int rcIprt = RTCrPkixSignatureCreateByObjId(&hSignature, pAlgorithm, false /*fSigning*/, pPublicKey, pParameters); if (RT_FAILURE(rcIprt)) return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_CIPHER_ALGO_NOT_KNOWN, "Unknown public key algorithm [IPRT]: %s", pAlgorithm->szObjId); RTCRDIGEST hDigest; rcIprt = RTCrDigestCreateByObjId(&hDigest, pAlgorithm); if (RT_SUCCESS(rcIprt)) { /* Calculate the digest. */ rcIprt = RTCrDigestUpdate(hDigest, pvData, cbData); if (RT_SUCCESS(rcIprt)) { rcIprt = RTCrPkixSignatureVerifyBitString(hSignature, hDigest, pSignatureValue); if (RT_FAILURE(rcIprt)) RTErrInfoSet(pErrInfo, rcIprt, "RTCrPkixSignatureVerifyBitString failed"); } else RTErrInfoSet(pErrInfo, rcIprt, "RTCrDigestUpdate failed"); RTCrDigestRelease(hDigest); } else RTErrInfoSetF(pErrInfo, rcIprt, "Unknown digest algorithm [IPRT]: %s", pAlgorithm->szObjId); RTCrPkixSignatureRelease(hSignature); #ifdef IPRT_WITH_OPENSSL /* * Validate using OpenSSL EVP. */ rtCrOpenSslInit(); /* Translate the algorithm ID into a EVP message digest type pointer. */ int iAlgoNid = OBJ_txt2nid(pAlgorithm->szObjId); if (iAlgoNid == NID_undef) return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN, "Unknown public key algorithm [OpenSSL]: %s", pAlgorithm->szObjId); const char *pszAlogSn = OBJ_nid2sn(iAlgoNid); const EVP_MD *pEvpMdType = EVP_get_digestbyname(pszAlogSn); if (!pEvpMdType) return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP, "EVP_get_digestbyname failed on %s (%s)", pszAlogSn, pAlgorithm->szObjId); /* Initialize the EVP message digest context. */ EVP_MD_CTX EvpMdCtx; EVP_MD_CTX_init(&EvpMdCtx); if (!EVP_VerifyInit_ex(&EvpMdCtx, pEvpMdType, NULL /*engine*/)) return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALOG_INIT_FAILED, "EVP_VerifyInit_ex failed (algorithm type is %s / %s)", pszAlogSn, pAlgorithm->szObjId); /* Create an EVP public key. */ int rcOssl; EVP_PKEY *pEvpPublicKey = EVP_PKEY_new(); if (pEvpPublicKey) { pEvpPublicKey->type = EVP_PKEY_type(pEvpMdType->required_pkey_type[0]); if (pEvpPublicKey->type != NID_undef) { const unsigned char *puchPublicKey = RTASN1BITSTRING_GET_BIT0_PTR(pPublicKey); if (d2i_PublicKey(pEvpPublicKey->type, &pEvpPublicKey, &puchPublicKey, RTASN1BITSTRING_GET_BYTE_SIZE(pPublicKey))) { /* Digest the data. */ EVP_VerifyUpdate(&EvpMdCtx, pvData, cbData); /* Verify the signature. */ if (EVP_VerifyFinal(&EvpMdCtx, RTASN1BITSTRING_GET_BIT0_PTR(pSignatureValue), RTASN1BITSTRING_GET_BYTE_SIZE(pSignatureValue), pEvpPublicKey) > 0) rcOssl = VINF_SUCCESS; else rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_VERIFY_FINAL_FAILED, "EVP_VerifyFinal failed"); } else rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_D2I_PUBLIC_KEY_FAILED, "d2i_PublicKey failed"); } else rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR, "EVP_PKEY_type(%d) failed", pEvpMdType->required_pkey_type[0]); /* Cleanup and return.*/ EVP_PKEY_free(pEvpPublicKey); } else rcOssl = RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "EVP_PKEY_new(%d) failed", pEvpMdType->required_pkey_type[0]); EVP_MD_CTX_cleanup(&EvpMdCtx); /* * Check the result. */ if (RT_SUCCESS(rcIprt) && RT_SUCCESS(rcOssl)) return VINF_SUCCESS; if (RT_FAILURE_NP(rcIprt) && RT_FAILURE_NP(rcOssl)) return rcIprt; AssertMsgFailed(("rcIprt=%Rrc rcOssl=%Rrc\n", rcIprt, rcOssl)); if (RT_FAILURE_NP(rcOssl)) return rcOssl; #endif /* IPRT_WITH_OPENSSL */ return rcIprt; }
static int openssl_pkey_read(lua_State*L) { EVP_PKEY * key = NULL; BIO* in = load_bio_object(L, 1); int priv = lua_isnoneornil(L, 2) ? 0 : auxiliar_checkboolean(L, 2); int fmt = luaL_checkoption(L, 3, "auto", format); const char* passphrase = luaL_optstring(L, 4, NULL); int type = -1; if (passphrase) { if (strcmp(passphrase, "rsa") == 0 || strcmp(passphrase, "RSA") == 0) type = EVP_PKEY_RSA; else if (strcmp(passphrase, "dsa") == 0 || strcmp(passphrase, "DSA") == 0) type = EVP_PKEY_DSA; else if (strcmp(passphrase, "ec") == 0 || strcmp(passphrase, "EC") == 0) type = EVP_PKEY_EC; } if (fmt == FORMAT_AUTO) { fmt = bio_is_der(in) ? FORMAT_DER : FORMAT_PEM; } if (!priv) { if (fmt == FORMAT_PEM) { key = PEM_read_bio_PUBKEY(in, NULL, NULL, (void*)passphrase); BIO_reset(in); if (key == NULL && type == EVP_PKEY_RSA) { RSA* rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL); if (rsa) { key = EVP_PKEY_new(); EVP_PKEY_assign_RSA(key, rsa); } } }else if (fmt == FORMAT_DER) { key = d2i_PUBKEY_bio(in, NULL); BIO_reset(in); if (!key && type!=-1) { char * bio_mem_ptr; long bio_mem_len; bio_mem_len = BIO_get_mem_data(in, &bio_mem_ptr); key = d2i_PublicKey(type, NULL, (const unsigned char **)&bio_mem_ptr, bio_mem_len); BIO_reset(in); } } } else { if (fmt == FORMAT_PEM) { key = PEM_read_bio_PrivateKey(in, NULL, NULL, (void*)passphrase); BIO_reset(in); }else if (fmt == FORMAT_DER) { if (passphrase) key = d2i_PKCS8PrivateKey_bio(in, NULL, NULL, (void*)passphrase); else key = d2i_PrivateKey_bio(in, NULL); BIO_reset(in); if (!key && type != -1) { char * bio_mem_ptr; long bio_mem_len; bio_mem_len = BIO_get_mem_data(in, &bio_mem_ptr); key = d2i_PrivateKey(type, NULL, (const unsigned char **)&bio_mem_ptr, bio_mem_len); BIO_reset(in); } } } BIO_free(in); if (key) { PUSH_OBJECT(key, "openssl.evp_pkey"); return 1; } return openssl_pushresult(L, 0); }
OP_STATUS CryptoSignature_impl::SetPublicKey(const UINT8* public_key, int key_length) { if (!public_key || key_length <= 0) return OpStatus::ERR_OUT_OF_RANGE; // This function supports public keys in different formats, such as // X509_PUBKEY and EVP_PKEY-with-RSA-key-only objects. // It should be made more generic, simple and straightforward: // only EVP_PKEY objects should be supported. // This function tries to decode data at "public_key" pointer as X509_PUBKEY, // if fails - as EVP_PKEY_RSA. // Clear the existing key, if any. if (m_keyspec) { EVP_PKEY_free(m_keyspec); m_keyspec = NULL; } // Try hypothesis: public key is X509_PUBKEY. // Temporary variable as recommended by "man d2i_X509". const unsigned char* public_key_tmp = public_key; // Construct X509_PUBKEY object. We own it. X509_PUBKEY* pubkey = d2i_X509_PUBKEY(NULL, &public_key_tmp, key_length); if (pubkey) { m_keyspec = X509_PUBKEY_get(pubkey); // X509_PUBKEY_get allocates new EVP_PKEY, so it's safe // to deallocate pubkey now. X509_PUBKEY_free(pubkey); } ERR_clear_error(); // Try hypothesis: public key is EVP_PKEY_RSA. if (m_keyspec == NULL) { switch (m_cipher_algorithm ) { case CRYPTO_CIPHER_TYPE_RSA: // Temporary variable my have changed its value, resetting. public_key_tmp = public_key; m_keyspec = d2i_PublicKey(EVP_PKEY_RSA, NULL, &public_key_tmp, key_length); ERR_clear_error(); break; default: return OpStatus::ERR_NOT_SUPPORTED; } } if (m_keyspec) return OpStatus::OK; return OpStatus::ERR; }
/*============================================================================ * OpcUa_P_OpenSSL_X509_SelfSigned_Custom_Create *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_X509_SelfSigned_Custom_Create( OpcUa_CryptoProvider* a_pProvider, OpcUa_Int32 a_serialNumber, OpcUa_UInt32 a_validToInSec, OpcUa_Crypto_NameEntry* a_pNameEntries, /* will be used for issuer and subject thus it's selfigned cert */ OpcUa_UInt a_nameEntriesCount, /* will be used for issuer and subject thus it's selfigned cert */ OpcUa_Key a_pSubjectPublicKey, /* EVP_PKEY* - type defines also public key algorithm */ OpcUa_Crypto_Extension* a_pExtensions, OpcUa_UInt a_extensionsCount, OpcUa_UInt a_signatureHashAlgorithm, /* EVP_sha1(),... */ OpcUa_Key a_pIssuerPrivateKey, /* EVP_PKEY* - type defines also signature algorithm */ OpcUa_ByteString* a_pCertificate) { OpcUa_UInt i; X509_NAME* pSubj = OpcUa_Null; X509V3_CTX ctx; const EVP_MD* pDigest = OpcUa_Null; X509* pCert = OpcUa_Null; EVP_PKEY* pSubjectPublicKey = OpcUa_Null; EVP_PKEY* pIssuerPrivateKey = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_SelfSigned_Custom_Create"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pNameEntries); OpcUa_ReturnErrorIfArgumentNull(a_pExtensions); OpcUa_ReturnErrorIfArgumentNull(a_pIssuerPrivateKey.Key.Data); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate); if(a_pSubjectPublicKey.Type != OpcUa_Crypto_KeyType_Rsa_Public) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } if(a_pIssuerPrivateKey.Type != OpcUa_Crypto_KeyType_Rsa_Private) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } pSubjectPublicKey = d2i_PublicKey(EVP_PKEY_RSA,OpcUa_Null,((const unsigned char**)&(a_pSubjectPublicKey.Key.Data)),a_pSubjectPublicKey.Key.Length); if(pSubjectPublicKey == OpcUa_Null) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } pIssuerPrivateKey = d2i_PrivateKey(EVP_PKEY_RSA,OpcUa_Null,((const unsigned char**)&(a_pIssuerPrivateKey.Key.Data)),a_pIssuerPrivateKey.Key.Length); if(pIssuerPrivateKey == OpcUa_Null) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* create new certificate object */ pCert = X509_new(); if(pCert == OpcUa_Null) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* set version of certificate (V3 since internal representation starts versioning from 0) */ if(X509_set_version(pCert, 2L) != 1) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* generate a unique number for a serial number if none provided. */ if(a_serialNumber == 0) { ASN1_INTEGER* pSerialNumber = X509_get_serialNumber(pCert); pSerialNumber->type = V_ASN1_INTEGER; pSerialNumber->data = OPENSSL_realloc(pSerialNumber->data, 16); pSerialNumber->length = 16; if(pSerialNumber->data == NULL || OpcUa_P_Guid_Create((OpcUa_Guid*)pSerialNumber->data) == NULL) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } } /* use the integer passed in - note the API should not be using a 32-bit integer - must fix sometime */ else if(ASN1_INTEGER_set(X509_get_serialNumber(pCert), a_serialNumber) == 0) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* add key to the request */ if(X509_set_pubkey(pCert, pSubjectPublicKey) != 1) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(pSubjectPublicKey != OpcUa_Null) { EVP_PKEY_free(pSubjectPublicKey); pSubjectPublicKey = OpcUa_Null; } /* assign the subject name */ pSubj = X509_NAME_new(); if(!pSubj) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* create and add entries to subject name */ for(i=0; i<a_nameEntriesCount; i++) { uStatus = OpcUa_P_OpenSSL_X509_Name_AddEntry(&pSubj, a_pNameEntries + i); OpcUa_GotoErrorIfBad(uStatus); } /* set subject name in request */ if(X509_set_subject_name(pCert, pSubj) != 1) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* set name of issuer (CA) */ if(X509_set_issuer_name(pCert, pSubj) != 1) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(!(X509_gmtime_adj(X509_get_notBefore(pCert), 0))) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* set ending time of the certificate */ if(!(X509_gmtime_adj(X509_get_notAfter(pCert), a_validToInSec))) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* add x509v3 extensions */ X509V3_set_ctx(&ctx, pCert, pCert, OpcUa_Null, OpcUa_Null, 0); for(i=0; i<a_extensionsCount; i++) { uStatus = OpcUa_P_OpenSSL_X509_AddCustomExtension(&pCert, a_pExtensions+i, &ctx); OpcUa_GotoErrorIfBad(uStatus); } /* sign certificate with the CA private key */ switch(a_signatureHashAlgorithm) { case OPCUA_P_SHA_160: pDigest = EVP_sha1(); break; case OPCUA_P_SHA_224: pDigest = EVP_sha224(); break; case OPCUA_P_SHA_256: pDigest = EVP_sha256(); break; case OPCUA_P_SHA_384: pDigest = EVP_sha384(); break; case OPCUA_P_SHA_512: pDigest = EVP_sha512(); break; default: uStatus = OpcUa_BadNotSupported; OpcUa_GotoErrorIfBad(uStatus); } if(!(X509_sign(pCert, pIssuerPrivateKey, pDigest))) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(X509_verify(pCert, pIssuerPrivateKey) <= 0) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(pIssuerPrivateKey != OpcUa_Null) { EVP_PKEY_free(pIssuerPrivateKey); pIssuerPrivateKey = OpcUa_Null; } if(pSubj != OpcUa_Null) { X509_NAME_free(pSubj); pSubj = OpcUa_Null; } /* prepare container */ memset(a_pCertificate, 0, sizeof(OpcUa_ByteString)); /* get required length for conversion target buffer */ a_pCertificate->Length = i2d_X509(pCert, NULL); if(a_pCertificate->Length <= 0) { /* conversion to DER not possible */ uStatus = OpcUa_Bad; } /* allocate conversion target buffer */ a_pCertificate->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pCertificate->Length); OpcUa_GotoErrorIfAllocFailed(a_pCertificate->Data); /* convert into DER */ a_pCertificate->Length = i2d_X509(pCert, &(a_pCertificate->Data)); if(a_pCertificate->Length <= 0) { /* conversion to DER not possible */ uStatus = OpcUa_Bad; } else { /* correct pointer incrementation by i2d_X509() */ a_pCertificate->Data -= a_pCertificate->Length; } X509_free(pCert); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; X509_free(pCert); if(pSubjectPublicKey != OpcUa_Null) { EVP_PKEY_free(pSubjectPublicKey); } if(pIssuerPrivateKey != OpcUa_Null) { EVP_PKEY_free(pIssuerPrivateKey); } if(pSubj != OpcUa_Null) { X509_NAME_free(pSubj); } OpcUa_FinishErrorHandling; }
int main(int argc, char **argv, char **envp) { #if 0 const char *algorithm = NULL; #else const char *algorithm = "md5"; #endif const char *key = NULL; const char *msg = NULL; const char *signature = NULL; #if 0 const char *type = NULL; #else const char *type = "rsa"; #endif xxxflag = false; if(!(prog = basename(argv[0]))) { fprintf(stderr, "err: basename: %s -- %s\n", strerror(errno), argv[0]); return(-1); /* NOTREACHED */ } { int ch = 0; #if 0 while((ch = getopt(argc, argv, "a:k:m:s:t:@")) != -1) { #else while((ch = getopt(argc, argv, "k:m:s:@")) != -1) { #endif switch (ch) { #if 0 case 'a': algorithm = optarg; break; #endif case 'k': key = optarg; break; case 'm': msg = optarg; break; case 's': signature = optarg; break; #if 0 case 't': type = optarg; break; #endif case '@': xxxflag = true; break; default: usage(); /* NOTREACHED */ break; } } argc -= optind; argv += optind; } if(argc || !algorithm || !key || !msg || !type) { usage(); /* NOTREACHED */ } return(sigcomp_main(algorithm, key, msg, signature, type)? 0: -1); /* NOTREACHED */ } static bool sigcomp_main(const char *const algorithm, const char *const key, const char *const msg, const char *const signature, const char *const type) { const EVP_MD *evp_md = NULL; BIGNUM *bn_key = NULL; BIGNUM *bn_msg = NULL; BIGNUM *bn_signature = NULL; ERR_load_crypto_strings(); if(!(evp_md = evp_md_with_algorithm(type, algorithm))) { fprintf(stderr, "err: algorithm: %s -- " "unknown algorithm for %s\n", algorithm, type); return(sigcomp_return(false, bn_key, bn_msg, bn_signature)); } /* key -> bn_key */ if(!(bn_key = BN_new())) { openssl_strerror("BN_new"); return(sigcomp_return(false, bn_key, bn_msg, bn_signature)); } if(!BN_hex2bn(&bn_key, (const char *)key)) { openssl_strerror("BN_hex2bn"); return(sigcomp_return(false, bn_key, bn_msg, bn_signature)); } /* msg -> bn_msg */ if(!(bn_msg = BN_new())) { openssl_strerror("BN_new"); return(sigcomp_return(false, bn_key, bn_msg, bn_signature)); } if(!BN_hex2bn(&bn_msg, (const char *)msg)) { openssl_strerror("BN_hex2bn"); return(sigcomp_return(false, bn_key, bn_msg, bn_signature)); } if(signature) { /* signature -> bn_signature */ if(!(bn_signature = BN_new())) { openssl_strerror("BN_new"); return(sigcomp_return(false, bn_key, bn_msg, bn_signature)); } if(!BN_hex2bn(&bn_signature, (const char *)signature)) { openssl_strerror("BN_hex2bn"); return(sigcomp_return(false, bn_key, bn_msg, bn_signature)); } if(!sigcomp_vrfy(evp_md, bn_key, bn_msg, bn_signature, type)) { return(sigcomp_return(false, bn_key, bn_msg, bn_signature)); } } else { if(!sigcomp_sign(evp_md, bn_key, bn_msg, type)) { return(sigcomp_return(false, bn_key, bn_msg, bn_signature)); } } return(sigcomp_return(true, bn_key, bn_msg, bn_signature)); } static bool sigcomp_return(const bool code, BIGNUM *bn_key, BIGNUM *bn_msg, BIGNUM *bn_signature) { if(bn_signature) { BN_free(bn_signature); bn_signature = NULL; } if(bn_msg) { BN_free(bn_msg); bn_msg = NULL; } if(bn_key) { BN_free(bn_key); bn_key = NULL; } return(code); } static bool sigcomp_sign(const EVP_MD *const evp_md, const BIGNUM *const bn_key, const BIGNUM *const bn_msg, const char *const type) { EVP_PKEY *pkey = NULL; unsigned char *key = NULL; unsigned char *msg = NULL; unsigned char *signature = NULL; unsigned char *ptr = NULL; int keylen = 0; int msglen = 0; int signaturelen = 0; int padding = 0; /* bn_key -> key */ if(!(keylen = BN_num_bytes(bn_key))) { openssl_strerror("BN_num_bytes"); return(sigcomp_sign_return(false, key, msg, signature, pkey)); } if(!(key = (unsigned char *)malloc(keylen))) { fprintf(stderr, "err: malloc: %s\n", strerror(errno)); return(sigcomp_sign_return(false, key, msg, signature, pkey)); } if(BN_bn2bin(bn_key, key) != keylen) { openssl_strerror("BN_bn2bin"); return(sigcomp_sign_return(false, key, msg, signature, pkey)); } #ifdef DEBUG dmp(stderr, "key", key, keylen); #endif // DEBUG /* bn_msg -> msg */ if(!(msglen = BN_num_bytes(bn_msg))) { openssl_strerror("BN_num_bytes"); return(sigcomp_sign_return(false, key, msg, signature, pkey)); } if(!(msg = (unsigned char *)malloc(msglen))) { fprintf(stderr, "err: malloc: %s\n", strerror(errno)); return(sigcomp_sign_return(false, key, msg, signature, pkey)); } if(BN_bn2bin(bn_msg, msg) != msglen) { openssl_strerror("BN_bn2bin"); return(sigcomp_sign_return(false, key, msg, signature, pkey)); } #ifdef DEBUG dmp(stderr, "msg", msg, msglen); #endif // DEBUG ptr = key; for( ; ; ) { if(!strcmp(type, "rsa")) { #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800fL) if(!(pkey = d2i_PrivateKey(EVP_PKEY_RSA, NULL, (const unsigned char **)&ptr, keylen))) { #else if(!(pkey = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &ptr, keylen))) { #endif openssl_strerror("d2i_PrivateKey"); return(sigcomp_sign_return(false, key, msg, signature, pkey)); } signaturelen = RSA_size(pkey->pkey.rsa); padding = RSA_PKCS1_PADDING; break; } if(!strcmp(type, "dsa")) { #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800fL) if(!(pkey = d2i_PrivateKey(EVP_PKEY_DSA, NULL, (const unsigned char **)&ptr, keylen))) { #else if(!(pkey = d2i_PrivateKey(EVP_PKEY_DSA, NULL, &ptr, keylen))) { #endif openssl_strerror("d2i_PrivateKey"); return(sigcomp_sign_return(false, key, msg, signature, pkey)); } fprintf(stderr, "err: type: %s -- not implemented\n", type); return(sigcomp_sign_return(false, key, msg, signature, pkey)); break; } fprintf(stderr, "err: type: %s -- unknown type\n", type); return(sigcomp_sign_return(false, key, msg, signature, pkey)); /* NOTREACHED */ } if(!(signature = (unsigned char *)malloc(signaturelen))) { fprintf(stderr, "err: malloc: %s\n", strerror(errno)); return(sigcomp_sign_return(false, key, msg, signature, pkey)); } RSA_private_encrypt(msglen, msg, signature, pkey->pkey.rsa, padding); #ifdef DEBUG dmp(stderr, "signature", signature, signaturelen); #endif // DEBUG sigcomp_sign_dump(key, keylen, msg, msglen, signature, signaturelen); return(sigcomp_sign_return(true, key, msg, signature, pkey)); } static void sigcomp_sign_dump(const unsigned char *const key, int keylen, const unsigned char *const msg, int msglen, const unsigned char *const signature, int signaturelen) { int d = 0; if(xxxflag) { #if 0 /* needless */ for(d = 0; d < msglen; d ++) { printf("%02x", msg[d]); } #endif for(d = 0; d < signaturelen; d ++) { printf("%02x", signature[d]); } printf("\n"); return; } printf("log:SigCompSign_Results (length:%d)\n", keylen + msglen + signaturelen); printf("log:| PrivateKey (length:%d)\n", keylen); printf("log:| | data = "); for(d = 0; d < keylen; d ++) { printf("%02x", key[d]); } printf("\n"); printf("log:| Message (length:%d)\n", msglen); printf("log:| | data = "); for(d = 0; d < msglen; d ++) { printf("%02x", msg[d]); } printf("\n"); printf("log:| Signature (length:%d)\n", signaturelen); printf("log:| | data = "); for(d = 0; d < signaturelen; d ++) { printf("%02x", signature[d]); } printf("\n"); return; } static bool sigcomp_sign_return(const bool code, unsigned char *key, unsigned char *msg, unsigned char *signature, EVP_PKEY *pkey) { if(pkey) { EVP_PKEY_free(pkey); pkey = NULL; } if(signature) { free(signature); signature = NULL; } if(msg) { free(msg); msg = NULL; } if(key) { free(key); key = NULL; } return(code); } static bool sigcomp_vrfy(const EVP_MD *const evp_md, const BIGNUM *const bn_key, const BIGNUM *const bn_msg, const BIGNUM *const bn_signature, const char *const type) { EVP_PKEY *pkey = NULL; unsigned char *key = NULL; unsigned char *msg = NULL; unsigned char *signature = NULL; unsigned char *to = NULL; unsigned char *ptr = NULL; int keylen = 0; int msglen = 0; int signaturelen = 0; int tolen = 0; int padding = 0; bool compare = true; /* bn_key -> key */ if(!(keylen = BN_num_bytes(bn_key))) { openssl_strerror("BN_num_bytes"); return(sigcomp_vrfy_return(false, key, msg, signature, to, pkey)); } if(!(key = (unsigned char *)malloc(keylen))) { fprintf(stderr, "err: malloc: %s\n", strerror(errno)); return(sigcomp_vrfy_return(false, key, msg, signature, to, pkey)); } if(BN_bn2bin(bn_key, key) != keylen) { openssl_strerror("BN_bn2bin"); return(sigcomp_vrfy_return(false, key, msg, signature, to, pkey)); } #ifdef DEBUG dmp(stderr, "key", key, keylen); #endif // DEBUG /* bn_msg -> msg */ if(!(msglen = BN_num_bytes(bn_msg))) { openssl_strerror("BN_num_bytes"); return(sigcomp_vrfy_return(false, key, msg, signature, to, pkey)); } if(!(msg = (unsigned char *)malloc(msglen))) { fprintf(stderr, "err: malloc: %s\n", strerror(errno)); return(sigcomp_vrfy_return(false, key, msg, signature, to, pkey)); } if(BN_bn2bin(bn_msg, msg) != msglen) { openssl_strerror("BN_bn2bin"); return(sigcomp_vrfy_return(false, key, msg, signature, to, pkey)); } #ifdef DEBUG dmp(stderr, "msg", msg, msglen); #endif // DEBUG /* bn_signature -> signature */ if(!(signaturelen = BN_num_bytes(bn_signature))) { openssl_strerror("BN_num_bytes"); return(sigcomp_vrfy_return(false, key, msg, signature, to, pkey)); } if(!(signature = (unsigned char *)malloc(signaturelen))) { fprintf(stderr, "err: malloc: %s\n", strerror(errno)); return(sigcomp_vrfy_return(false, key, msg, signature, to, pkey)); } if(BN_bn2bin(bn_signature, signature) != signaturelen) { openssl_strerror("BN_bn2bin"); return(sigcomp_vrfy_return(false, key, msg, signature, to, pkey)); } #ifdef DEBUG dmp(stderr, "signature", signature, signaturelen); #endif // DEBUG ptr = key; for( ; ; ) { if(!strcmp(type, "rsa")) { #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800fL) if(!(pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, (const unsigned char **)&ptr, keylen))) { #else if(!(pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &ptr, keylen))) { #endif openssl_strerror("d2i_PublicKey"); return(sigcomp_vrfy_return(false, key, msg, signature, to, pkey)); } tolen = RSA_size(pkey->pkey.rsa); padding = RSA_PKCS1_PADDING; break; } if(!strcmp(type, "dsa")) { #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800fL) if(!(pkey = d2i_PublicKey(EVP_PKEY_DSA, NULL, (const unsigned char **)&ptr, keylen))) { #else if(!(pkey = d2i_PublicKey(EVP_PKEY_DSA, NULL, &ptr, keylen))) { #endif openssl_strerror("d2i_PublicKey"); return(sigcomp_vrfy_return(false, key, msg, signature, to, pkey)); } fprintf(stderr, "err: type: %s -- not implemented\n", type); return(sigcomp_vrfy_return(false, key, msg, signature, to, pkey)); /* NOTREACHED */ break; } fprintf(stderr, "err: type: %s -- unknown type\n", type); return(sigcomp_vrfy_return(false, key, msg, signature, to, pkey)); /* NOTREACHED */ } if(!(to = (unsigned char *)malloc(tolen))) { fprintf(stderr, "err: malloc: %s\n", strerror(errno)); return(sigcomp_vrfy_return(false, key, msg, signature, to, pkey)); } if(RSA_public_decrypt(signaturelen, signature, to, pkey->pkey.rsa, padding) < 0) { openssl_strerror("RSA_public_decrypt"); return(sigcomp_vrfy_return(true, key, msg, signature, to, pkey)); } if(memcmp(msg, to, msglen)) { compare = false; } sigcomp_vrfy_dump(compare, key, keylen, msg, msglen, signature, signaturelen, to, tolen); return(sigcomp_vrfy_return(true, key, msg, signature, to, pkey)); } static void sigcomp_vrfy_dump(const bool code, const unsigned char *const key, int keylen, const unsigned char *const msg, int msglen, const unsigned char *const signature, int signaturelen, const unsigned char *const to, int tolen) { int d = 0; printf("log:SigCompVrfy_Results (length:%d)\n", keylen + msglen + signaturelen + tolen); printf("log:| PublicKey (length:%d)\n", keylen); printf("log:| | data = "); for(d = 0; d < keylen; d ++) { printf("%02x", key[d]); } printf("\n"); printf("log:| Message (length:%d)\n", msglen); printf("log:| | data = "); for(d = 0; d < msglen; d ++) { printf("%02x", msg[d]); } printf("\n"); printf("log:| Signature (length:%d)\n", signaturelen + tolen); printf("log:| | status = %s\n", code? "true": "false"); printf("log:| | Encrypted (length:%d)\n", signaturelen); printf("log:| | | data = "); for(d = 0; d < signaturelen; d ++) { printf("%02x", signature[d]); } printf("\n"); printf("log:| | Decrypted (length:%d)\n", tolen); printf("log:| | | data = "); for(d = 0; d < tolen; d ++) { printf("%02x", to[d]); } printf("\n"); return; } static bool sigcomp_vrfy_return(const bool code, unsigned char *key, unsigned char *msg, unsigned char *signature, unsigned char *to, EVP_PKEY *pkey) { if(pkey) { EVP_PKEY_free(pkey); pkey = NULL; } if(to) { free(to); to = NULL; } if(signature) { free(signature); signature = NULL; } if(msg) { free(msg); msg = NULL; } if(key) { free(key); key = NULL; } return(code); } static const EVP_MD * evp_md_with_algorithm(const char *const type, const char *const algorithm) { const EVP_MD *evp_md = NULL; bool dsa = false; bool rsa = false; for( ; ; ) { if(!strcmp(type, "dsa")) { dsa = true; break; } if(!strcmp(type, "rsa")) { rsa = true; break; } break; } for( ; ; ) { if(dsa && !strcmp(algorithm, "dss1")) { evp_md = EVP_dss1(); break; } if(rsa && !strcmp(algorithm, "md2")) { evp_md = EVP_md2(); break; } if(rsa && !strcmp(algorithm, "md4")) { evp_md = EVP_md4(); break; } if(rsa && !strcmp(algorithm, "md5")) { evp_md = EVP_md5(); break; } #if ! defined(__linux__) if(rsa && !strcmp(algorithm, "mdc2")) { evp_md = EVP_mdc2(); break; } #endif if(rsa && !strcmp(algorithm, "ripemd160")) { evp_md = EVP_ripemd160(); break; } if(rsa && !strcmp(algorithm, "sha1")) { evp_md = EVP_sha1(); break; } break; } return(evp_md); } static void openssl_strerror(const char *const label) { unsigned long code = 0; while((code = ERR_get_error())) { fprintf(stderr, "err: %s: %s\n", label, ERR_error_string(code, NULL)); } return; }