bool OSSLEVPHashAlgorithm::hashFinal(ByteString& hashedData) { if (!HashAlgorithm::hashFinal(hashedData)) { return false; } hashedData.resize(EVP_MD_size(getEVPHash())); unsigned int outLen = hashedData.size(); if (!EVP_DigestFinal_ex(curCTX, &hashedData[0], &outLen)) { ERROR_MSG("EVP_DigestFinal failed"); EVP_MD_CTX_free(curCTX); curCTX = NULL; return false; } hashedData.resize(outLen); EVP_MD_CTX_free(curCTX); curCTX = NULL; return true; }
bool OSSLEVPMacAlgorithm::signFinal(ByteString& signature) { if (!MacAlgorithm::signFinal(signature)) { return false; } signature.resize(EVP_MD_size(getEVPHash())); unsigned int outLen = signature.size(); if (!HMAC_Final(&curCTX, &signature[0], &outLen)) { ERROR_MSG("HMAC_Final failed"); HMAC_CTX_cleanup(&curCTX); return false; } signature.resize(outLen); HMAC_CTX_cleanup(&curCTX); return true; }
bool BotanSymmetricAlgorithm::decryptUpdate(const ByteString& encryptedData, ByteString& data) { if (!SymmetricAlgorithm::decryptUpdate(encryptedData, data)) { delete cryption; cryption = NULL; return false; } // Write data try { if (encryptedData.size() > 0) cryption->write(encryptedData.const_byte_str(), encryptedData.size()); } catch (...) { ERROR_MSG("Failed to write to the decryption token"); ByteString dummy; SymmetricAlgorithm::decryptFinal(dummy); delete cryption; cryption = NULL; return false; } // Read data int bytesRead = 0; try { size_t outLen = cryption->remaining(); data.resize(outLen); if (outLen > 0) bytesRead = cryption->read(&data[0], outLen); } catch (...) { ERROR_MSG("Failed to decrypt the data"); ByteString dummy; SymmetricAlgorithm::decryptFinal(dummy); delete cryption; cryption = NULL; return false; } // Resize the output block data.resize(bytesRead); currentBufferSize -= bytesRead; return true; }
// Decryption functions bool OSSLRSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding) { // Check if the private key is the right type if (!privateKey->isOfType(OSSLRSAPrivateKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } // Retrieve the OpenSSL key object RSA* rsa = ((OSSLRSAPrivateKey*) privateKey)->getOSSLKey(); // Check the input size if (encryptedData.size() != (size_t) RSA_size(rsa)) { ERROR_MSG("Invalid amount of input data supplied for RSA decryption"); return false; } // Determine the OpenSSL padding algorithm int osslPadding = 0; switch (padding) { case AsymMech::RSA_PKCS: osslPadding = RSA_PKCS1_PADDING; break; case AsymMech::RSA_PKCS_OAEP: osslPadding = RSA_PKCS1_OAEP_PADDING; break; case AsymMech::RSA: osslPadding = RSA_NO_PADDING; break; default: ERROR_MSG("Invalid padding mechanism supplied (%i)", padding); return false; } // Perform the RSA operation data.resize(RSA_size(rsa)); int decSize = RSA_private_decrypt(encryptedData.size(), (unsigned char*) encryptedData.const_byte_str(), &data[0], rsa, osslPadding); if (decSize == -1) { ERROR_MSG("RSA private key decryption failed (0x%08X)", ERR_get_error()); return false; } data.resize(decSize); return true; }
// Set from Botan representation void BotanEDPublicKey::setFromBotan(const Botan::Public_Key* inEDKEY) { Botan::OID oid; std::vector<uint8_t> pub; for (;;) { const Botan::Curve25519_PublicKey* x25519 = dynamic_cast<const Botan::Curve25519_PublicKey*>(inEDKEY); if (x25519) { oid = x25519_oid; pub = x25519->public_value(); break; } const Botan::Ed25519_PublicKey* ed25519 = dynamic_cast<const Botan::Ed25519_PublicKey*>(inEDKEY); if (ed25519) { oid = ed25519_oid; pub = ed25519->get_public_key(); break; } return; } ByteString inEC = BotanUtil::oid2ByteString(oid); setEC(inEC); ByteString inA; inA.resize(pub.size()); memcpy(&inA[0], &pub[0], pub.size()); setA(DERUTIL::raw2Octet(inA)); }
// Encode into PKCS#8 DER ByteString OSSLECPrivateKey::PKCS8Encode() { ByteString der; if (eckey == NULL) return der; EVP_PKEY* pkey = EVP_PKEY_new(); if (pkey == NULL) return der; if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { EVP_PKEY_free(pkey); return der; } PKCS8_PRIV_KEY_INFO* p8inf = EVP_PKEY2PKCS8(pkey); EVP_PKEY_free(pkey); if (p8inf == NULL) return der; int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf, NULL); if (len < 0) { PKCS8_PRIV_KEY_INFO_free(p8inf); return der; } der.resize(len); unsigned char* priv = &der[0]; int len2 = i2d_PKCS8_PRIV_KEY_INFO(p8inf, &priv); PKCS8_PRIV_KEY_INFO_free(p8inf); if (len2 != len) der.wipe(); return der; }
bool BotanDSA::signFinal(ByteString& signature) { if (!AsymmetricAlgorithm::signFinal(signature)) { return false; } // Perform the signature operation Botan::SecureVector<Botan::byte> signResult; try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); signResult = signer->signature(*rng->getRNG()); } catch (...) { ERROR_MSG("Could not sign the data"); delete signer; signer = NULL; return false; } // Return the result signature.resize(signResult.size()); memcpy(&signature[0], signResult.begin(), signResult.size()); delete signer; signer = NULL; return true; }
// Encode into PKCS#8 DER ByteString BotanDSAPrivateKey::PKCS8Encode() { ByteString der; createBotanKey(); if (dsa == NULL) return der; const Botan::SecureVector<Botan::byte> ber = Botan::PKCS8::BER_encode(*dsa); der.resize(ber.size()); memcpy(&der[0], ber.begin(), ber.size()); return der; }
// Signing functions bool OSSLECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const std::string mechanism) { std::string lowerMechanism; lowerMechanism.resize(mechanism.size()); std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower); if (lowerMechanism.compare("ecdsa")) { ERROR_MSG("Invalid mechanism supplied (%s)", mechanism.c_str()); return false; } // Check if the private key is the right type if (!privateKey->isOfType(OSSLECPrivateKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } OSSLECPrivateKey* pk = (OSSLECPrivateKey*) privateKey; EC_KEY* eckey = pk->getOSSLKey(); if (eckey == NULL) { ERROR_MSG("Could not get the OpenSSL private key"); return false; } // Use the OpenSSL implementation and not any engine ECDSA_set_method(eckey, ECDSA_OpenSSL()); // Perform the signature operation size_t len = pk->getOrderLength(); if (len == 0) { ERROR_MSG("Could not get the order length"); return false; } signature.resize(2 * len); memset(&signature[0], 0, 2 * len); ECDSA_SIG *sig = ECDSA_do_sign(dataToSign.const_byte_str(), dataToSign.size(), eckey); if (sig == NULL) { ERROR_MSG("ECDSA sign failed (0x%08X)", ERR_get_error()); return false; } // Store the 2 values with padding BN_bn2bin(sig->r, &signature[len - BN_num_bytes(sig->r)]); BN_bn2bin(sig->s, &signature[2 * len - BN_num_bytes(sig->s)]); ECDSA_SIG_free(sig); return true; }
bool BotanDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey) { // Check parameters if ((ppSymmetricKey == NULL) || (publicKey == NULL) || (privateKey == NULL)) { return false; } // Get keys Botan::DH_PublicKey* pub = ((BotanDHPublicKey*) publicKey)->getBotanKey(); Botan::DH_PrivateKey* priv = ((BotanDHPrivateKey*) privateKey)->getBotanKey(); if (pub == NULL || priv == NULL) { ERROR_MSG("Failed to get Botan DH keys"); return false; } // Derive the secret Botan::SymmetricKey sk; try { Botan::PK_Key_Agreement ka(*priv, "Raw"); sk = ka.derive_key(0, pub->public_value()); } catch (...) { ERROR_MSG("Botan DH key agreement failed"); return false; } ByteString secret; secret.resize(sk.length()); memcpy(&secret[0], sk.begin(), sk.length()); *ppSymmetricKey = new SymmetricKey(sk.length() * 8); if (*ppSymmetricKey == NULL) { ERROR_MSG("Can't create DH secret"); return false; } if (!(*ppSymmetricKey)->setKeyBits(secret)) { delete *ppSymmetricKey; *ppSymmetricKey = NULL; return false; } return true; }
// Convert an OpenSSL BIGNUM to a ByteString ByteString OSSL::bn2ByteString(const BIGNUM* bn) { ByteString rv; if (bn != NULL) { rv.resize(BN_num_bytes(bn)); BN_bn2bin(bn, &rv[0]); } return rv; }
bool OSSLGOST::signFinal(ByteString& signature) { // Save necessary state before calling super class signFinal OSSLGOSTPrivateKey* pk = (OSSLGOSTPrivateKey*) currentPrivateKey; if (!AsymmetricAlgorithm::signFinal(signature)) { return false; } // Perform the signature operation EVP_PKEY* pkey = pk->getOSSLKey(); unsigned int outLen; if (pkey == NULL) { ERROR_MSG("Could not get the OpenSSL private key"); EVP_MD_CTX_cleanup(&curCTX); return false; } signature.resize(EVP_PKEY_size(pkey)); outLen = signature.size(); if (!EVP_SignFinal(&curCTX, &signature[0], &outLen, pkey)) { ERROR_MSG("EVP_SignFinal failed"); EVP_MD_CTX_cleanup(&curCTX); return false; } signature.resize(outLen); EVP_MD_CTX_cleanup(&curCTX); return true; }
// Convert an OpenSSL EC GROUP to a ByteString ByteString OSSL::grp2ByteString(const EC_GROUP* grp) { ByteString rv; if (grp != NULL) { rv.resize(i2d_ECPKParameters(grp, NULL)); unsigned char *p = &rv[0]; i2d_ECPKParameters(grp, &p); } return rv; }
// Convert an OpenSSL EC POINT in the given EC GROUP to a ByteString ByteString OSSL::pt2ByteString(const EC_POINT* pt, const EC_GROUP* grp) { ByteString raw; if (pt == NULL || grp == NULL) return raw; size_t len = EC_POINT_point2oct(grp, pt, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); raw.resize(len); EC_POINT_point2oct(grp, pt, POINT_CONVERSION_UNCOMPRESSED, &raw[0], len, NULL); return DERUTIL::raw2Octet(raw); }
// Convert an OpenSSL NID to a ByteString ByteString OSSL::oid2ByteString(int nid) { ByteString rv; if (nid != NID_undef) { rv.resize(i2d_ASN1_OBJECT(OBJ_nid2obj(nid), NULL)); unsigned char *p = &rv[0]; i2d_ASN1_OBJECT(OBJ_nid2obj(nid), &p); } return rv; }
// Set from OpenSSL representation void OSSLGOSTPrivateKey::setFromOSSL(const EVP_PKEY* pkey) { const EC_KEY* eckey = (const EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey); const BIGNUM* priv = EC_KEY_get0_private_key(eckey); setD(OSSL::bn2ByteString(priv)); ByteString inEC; int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)); inEC.resize(i2d_ASN1_OBJECT(OBJ_nid2obj(nid), NULL)); unsigned char *p = &inEC[0]; i2d_ASN1_OBJECT(OBJ_nid2obj(nid), &p); setEC(inEC); }
bool BotanSymmetricAlgorithm::decryptFinal(ByteString& data) { if (!SymmetricAlgorithm::decryptFinal(data)) { delete cryption; cryption = NULL; return false; } // Read data int bytesRead = 0; try { cryption->end_msg(); size_t outLen = cryption->remaining(); data.resize(outLen); if (outLen > 0) bytesRead = cryption->read(&data[0], outLen); } catch (...) { ERROR_MSG("Failed to decrypt the data"); delete cryption; cryption = NULL; return false; } // Clean up delete cryption; cryption = NULL; // Resize the output block data.resize(bytesRead); return true; }
// Set from OpenSSL representation void OSSLGOSTPublicKey::setFromOSSL(const EVP_PKEY* pkey) { ByteString der; int len = i2d_PUBKEY((EVP_PKEY*) pkey, NULL); if (len != 37 + 64) { ERROR_MSG("bad GOST public key encoding length %d", len); return; } der.resize(len); unsigned char *p = &der[0]; i2d_PUBKEY((EVP_PKEY*) pkey, &p); // can check: der is prefix + 64 bytes setQ(der.substr(37)); ByteString inEC; const EC_KEY* eckey = (const EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey); int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)); inEC.resize(i2d_ASN1_OBJECT(OBJ_nid2obj(nid), NULL)); p = &inEC[0]; i2d_ASN1_OBJECT(OBJ_nid2obj(nid), &p); setEC(inEC); }
// Encode into PKCS#8 DER ByteString BotanRSAPrivateKey::PKCS8Encode() { ByteString der; createBotanKey(); if (rsa == NULL) return der; #if BOTAN_VERSION_MINOR == 11 const Botan::secure_vector<Botan::byte> ber = Botan::PKCS8::BER_encode(*rsa); #else const Botan::SecureVector<Botan::byte> ber = Botan::PKCS8::BER_encode(*rsa); #endif der.resize(ber.size()); memcpy(&der[0], &ber[0], ber.size()); return der; }
bool OSAttribute::peekValue(ByteString& value) const { switch (attributeType) { case BOOL: value.resize(sizeof(boolValue)); memcpy(&value[0], &boolValue, value.size()); return true; case ULONG: value.resize(sizeof(ulongValue)); memcpy(&value[0], &ulongValue, value.size()); return true; case BYTESTR: value.resize(byteStrValue.size()); memcpy(&value[0], byteStrValue.const_byte_str(), value.size()); return true; default: return false; } }
// Encode into PKCS#8 DER ByteString BotanGOSTPrivateKey::PKCS8Encode() { ByteString der; createBotanKey(); if (eckey == NULL) return der; // Force EC_DOMPAR_ENC_OID const size_t PKCS8_VERSION = 0; #if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0) const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID); const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters); const Botan::secure_vector<Botan::byte> ber = Botan::DER_Encoder() .start_cons(Botan::SEQUENCE) .encode(PKCS8_VERSION) .encode(alg_id) .encode(eckey->private_key_bits(), Botan::OCTET_STRING) .end_cons() .get_contents(); #elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID); const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters); const Botan::secure_vector<Botan::byte> ber = Botan::DER_Encoder() .start_cons(Botan::SEQUENCE) .encode(PKCS8_VERSION) .encode(alg_id) .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING) .end_cons() .get_contents(); #else const Botan::MemoryVector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID); const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters); const Botan::SecureVector<Botan::byte> ber = Botan::DER_Encoder() .start_cons(Botan::SEQUENCE) .encode(PKCS8_VERSION) .encode(alg_id) .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING) .end_cons() .get_contents(); #endif der.resize(ber.size()); memcpy(&der[0], &ber[0], ber.size()); return der; }
void OSSLGOSTPublicKey::setQ(const ByteString& inQ) { GOSTPublicKey::setQ(inQ); if (inQ.size() != 64) { ERROR_MSG("bad GOST public key size %zu", q.size()); return; } ByteString der; der.resize(37 + 64); memcpy(&der[0], gost_prefix, 37); memcpy(&der[37], inQ.const_byte_str(), 64); const unsigned char *p = &der[0]; if (d2i_PUBKEY(&pkey, &p, (long) der.size()) == NULL) ERROR_MSG("d2i_PUBKEY failed"); }
bool OSSLDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey) { // Check parameters if ((ppSymmetricKey == NULL) || (publicKey == NULL) || (privateKey == NULL)) { return false; } // Get keys DH *pub = ((OSSLDHPublicKey *)publicKey)->getOSSLKey(); DH *priv = ((OSSLDHPrivateKey *)privateKey)->getOSSLKey(); if (pub == NULL || pub->pub_key == NULL || priv == NULL) { ERROR_MSG("Failed to get OpenSSL DH keys"); return false; } // Derive the secret ByteString secret; secret.resize(DH_size(priv));; if (DH_compute_key(&secret[0], pub->pub_key, priv) <= 0) { ERROR_MSG("DH key derivation failed (0x%08X)", ERR_get_error()); return false; } *ppSymmetricKey = new SymmetricKey; if (*ppSymmetricKey == NULL) return false; if (!(*ppSymmetricKey)->setKeyBits(secret)) { delete *ppSymmetricKey; *ppSymmetricKey = NULL; return false; } return true; }
bool BotanGOST::signFinal(ByteString& signature) { if (!AsymmetricAlgorithm::signFinal(signature)) { return false; } // Perform the signature operation #if BOTAN_VERSION_MINOR == 11 std::vector<Botan::byte> signResult; #else Botan::SecureVector<Botan::byte> signResult; #endif try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); signResult = signer->signature(*rng->getRNG()); } catch (...) { ERROR_MSG("Could not sign the data"); delete signer; signer = NULL; return false; } // Return the result signature.resize(signResult.size()); #if BOTAN_VERSION_MINOR == 11 memcpy(&signature[0], signResult.data(), signResult.size()); #else memcpy(&signature[0], signResult.begin(), signResult.size()); #endif delete signer; signer = NULL; return true; }
// Signing functions bool OSSLDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param /* = NULL */, const size_t paramLen /* = 0 */) { if (mechanism == AsymMech::DSA) { // Separate implementation for DSA signing without hash computation // Check if the private key is the right type if (!privateKey->isOfType(OSSLDSAPrivateKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } OSSLDSAPrivateKey* pk = (OSSLDSAPrivateKey*) privateKey; DSA* dsa = pk->getOSSLKey(); // Perform the signature operation unsigned int sigLen = pk->getOutputLength(); signature.resize(sigLen); memset(&signature[0], 0, sigLen); int dLen = dataToSign.size(); DSA_SIG* sig = DSA_do_sign(dataToSign.const_byte_str(), dLen, dsa); if (sig == NULL) return false; // Store the 2 values with padding BN_bn2bin(sig->r, &signature[sigLen / 2 - BN_num_bytes(sig->r)]); BN_bn2bin(sig->s, &signature[sigLen - BN_num_bytes(sig->s)]); DSA_SIG_free(sig); return true; } else { // Call default implementation return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen); } }
// Encode into PKCS#8 DER ByteString BotanECDHPrivateKey::PKCS8Encode() { ByteString der; createBotanKey(); if (eckey == NULL) return der; const size_t PKCS8_VERSION = 0; // No OID for ECDH const Botan::OID oid("1.2.840.10045.2.1"); // Force EC_DOMPAR_ENC_OID const Botan::MemoryVector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID); const Botan::AlgorithmIdentifier alg_id(oid, parameters); const Botan::SecureVector<Botan::byte> ber = Botan::DER_Encoder() .start_cons(Botan::SEQUENCE) .encode(PKCS8_VERSION) .encode(alg_id) .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING) .end_cons() .get_contents(); der.resize(ber.size()); memcpy(&der[0], ber.begin(), ber.size()); return der; }
bool OSSLDSA::signFinal(ByteString& signature) { // Save necessary state before calling super class signFinal OSSLDSAPrivateKey* pk = (OSSLDSAPrivateKey*) currentPrivateKey; if (!AsymmetricAlgorithm::signFinal(signature)) { return false; } ByteString hash; bool bFirstResult = pCurrentHash->hashFinal(hash); delete pCurrentHash; pCurrentHash = NULL; if (!bFirstResult) { return false; } DSA* dsa = pk->getOSSLKey(); // Perform the signature operation unsigned int sigLen = pk->getOutputLength(); signature.resize(sigLen); memset(&signature[0], 0, sigLen); DSA_SIG* sig = DSA_do_sign(&hash[0], hash.size(), dsa); if (sig == NULL) return false; // Store the 2 values with padding BN_bn2bin(sig->r, &signature[sigLen / 2 - BN_num_bytes(sig->r)]); BN_bn2bin(sig->s, &signature[sigLen - BN_num_bytes(sig->s)]); DSA_SIG_free(sig); return true; }
bool OSSLEVPMacAlgorithm::verifyFinal(ByteString& signature) { if (!MacAlgorithm::verifyFinal(signature)) { return false; } ByteString macResult; unsigned int outLen = EVP_MD_size(getEVPHash()); macResult.resize(outLen); if (!HMAC_Final(&curCTX, &macResult[0], &outLen)) { ERROR_MSG("HMAC_Final failed"); HMAC_CTX_cleanup(&curCTX); return false; } HMAC_CTX_cleanup(&curCTX); return macResult == signature; }
static bool decodeAttributeMap(std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& map, const unsigned char *binary, size_t size) { for (size_t pos = 0; pos < size; ) { // finished? if (pos == size) break; CK_ATTRIBUTE_TYPE attrType; if (pos + sizeof(attrType) > size) { goto overrun; } memcpy(&attrType, binary + pos, sizeof(attrType)); pos += sizeof(attrType); AttributeKind attrKind; if (pos + sizeof(AttributeKind) > size) { goto overrun; } memcpy(&attrKind, binary + pos, sizeof(attrKind)); pos += sizeof(attrKind); // Verify using attributeKind()? switch (attrKind) { case akBoolean: { bool value; if (pos + sizeof(value) > size) { goto overrun; } memcpy(&value, binary + pos, sizeof(value)); pos += sizeof(value); map.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attrType, value)); } break; case akInteger: { unsigned long value; if (pos + sizeof(value) > size) { goto overrun; } memcpy(&value, binary + pos, sizeof(value)); pos += sizeof(value); map.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attrType, value)); } break; case akBinary: { ByteString value; unsigned long len; if (pos + sizeof(len) > size) { goto overrun; } memcpy(&len, binary + pos, sizeof(len)); pos += sizeof(len); if (pos + len > size) { goto overrun; } value.resize(len); memcpy(&value[0], binary + pos, len); pos += len; map.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attrType, value)); } break; case akMechSet: { unsigned long len; if (pos + sizeof(len) > size) { goto overrun; } memcpy(&len, binary + pos, sizeof(len)); pos += sizeof(len); if (pos + len > size) { goto overrun; } std::set<CK_MECHANISM_TYPE> value; if (!decodeMechanismTypeSet(value, binary + pos, len)) { return false; } pos += len; map.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attrType, value)); } break; default: ERROR_MSG("unsupported attribute kind in attribute map"); return false; } } return true; overrun: ERROR_MSG("attribute map template overrun"); return false; }
// Decryption functions bool BotanRSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding) { // Check if the private key is the right type if (!privateKey->isOfType(BotanRSAPrivateKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } std::string eme; switch (padding) { case AsymMech::RSA_PKCS: eme = "PKCS1v15"; break; case AsymMech::RSA_PKCS_OAEP: eme = "EME1(SHA-160)"; break; case AsymMech::RSA: eme = "Raw"; break; default: ERROR_MSG("Invalid padding mechanism supplied (%i)", padding); return false; } BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) privateKey; Botan::RSA_PrivateKey* botanKey = pk->getBotanKey(); if (!botanKey) { ERROR_MSG("Could not get the Botan private key"); return false; } Botan::PK_Decryptor_EME* decryptor = NULL; try { decryptor = new Botan::PK_Decryptor_EME(*botanKey, eme); } catch (...) { ERROR_MSG("Could not create the decryptor token"); return false; } // Perform the decryption operation #if BOTAN_VERSION_MINOR == 11 Botan::secure_vector<Botan::byte> decResult; #else Botan::SecureVector<Botan::byte> decResult; #endif try { decResult = decryptor->decrypt(encryptedData.const_byte_str(), encryptedData.size()); } catch (...) { ERROR_MSG("Could not decrypt the data"); delete decryptor; return false; } // Return the result if (padding == AsymMech::RSA) { // We compensate that Botan removes leading zeros int modSize = pk->getN().size(); int decSize = decResult.size(); data.resize(modSize); #if BOTAN_VERSION_MINOR == 11 memcpy(&data[0] + modSize - decSize, decResult.data(), decSize); #else memcpy(&data[0] + modSize - decSize, decResult.begin(), decSize); #endif } else { data.resize(decResult.size()); #if BOTAN_VERSION_MINOR == 11 memcpy(&data[0], decResult.data(), decResult.size()); #else memcpy(&data[0], decResult.begin(), decResult.size()); #endif } delete decryptor; return true; }