Skip to content

Commit

Permalink
Merge pull request #36 from IBM-Swift/deallocate
Browse files Browse the repository at this point in the history
fix: Added deallocate functions
  • Loading branch information
billabt authored Feb 27, 2019
2 parents dc6f4fa + fd6adcd commit f2e3705
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 102 deletions.
143 changes: 74 additions & 69 deletions Sources/CryptorRSA/CryptorRSA.swift
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,18 @@ public class CryptorRSA {
let rsaEncryptCtx = EVP_CIPHER_CTX_new_wrapper()
EVP_CIPHER_CTX_init_wrapper(rsaEncryptCtx)

// get rsaKey
guard let rsaKey = EVP_PKEY_get1_RSA(.make(optional: key.reference)) else {
let source = "Couldn't create key reference from key data"
if let reason = CryptorRSA.getLastError(source: source) {
throw Error(code: ERR_ADD_KEY, reason: reason)
}
throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.")
}
defer {
RSA_free(rsaKey)
}

// Set the additional authenticated data (aad) as the RSA key modulus and publicExponent in an ASN1 sequence.
guard let aad = key.publicKeyBytes else {
let source = "Encryption failed"
Expand Down Expand Up @@ -368,7 +380,7 @@ public class CryptorRSA {
// Set the aeskey and iv for the symmetric encryption.
EVP_EncryptInit_ex(rsaEncryptCtx, nil, nil, aeskey, iv) == 1,
// Encrypt the aes key using the rsa public key with SHA1, OAEP padding.
RSA_public_encrypt(Int32(keySize), aeskey, encryptedKey, .make(optional: key.reference), RSA_PKCS1_OAEP_PADDING) == encryptedCapacity,
RSA_public_encrypt(Int32(keySize), aeskey, encryptedKey, .make(optional: rsaKey), RSA_PKCS1_OAEP_PADDING) == encryptedCapacity,
// Add the aad to the encryption context.
// This is used in generating the GCM tag. We don't use this processedLength.
EVP_EncryptUpdate(rsaEncryptCtx, nil, &processedLength, [UInt8](aad), Int32(aad.count)) == 1
Expand Down Expand Up @@ -417,16 +429,13 @@ public class CryptorRSA {
}

func encryptedCBC(with key: PublicKey) throws -> EncryptedData? {
// Convert RSA key to EVP
// Copy the EVP Key
var evp_key = EVP_PKEY_new()
var rc = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference))
guard rc == 1 else {
let source = "Couldn't create key reference from key data"
if let reason = CryptorRSA.getLastError(source: source) {

throw Error(code: ERR_ADD_KEY, reason: reason)
}
throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.")
let rsa = EVP_PKEY_get1_RSA(.make(optional: key.reference))
EVP_PKEY_set1_RSA(evp_key, rsa)
RSA_free(rsa)
defer {
EVP_PKEY_free(evp_key)
}

// TODO: hash type option is not being used right now.
Expand All @@ -438,23 +447,34 @@ public class CryptorRSA {
defer {
EVP_CIPHER_CTX_reset_wrapper(rsaEncryptCtx)
EVP_CIPHER_CTX_free_wrapper(rsaEncryptCtx)
EVP_PKEY_free(evp_key)
}

EVP_CIPHER_CTX_set_padding(rsaEncryptCtx, padding)

// Initialize the AES encryption key array (of size 1)
typealias UInt8Ptr = UnsafeMutablePointer<UInt8>?
var ek: UInt8Ptr
ek = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(EVP_PKEY_size(evp_key)))
ek = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(EVP_PKEY_size(.make(optional: key.reference))))
let ekPtr = UnsafeMutablePointer<UInt8Ptr>.allocate(capacity: MemoryLayout<UInt8Ptr>.size)
ekPtr.pointee = ek

// Assign size of the corresponding cipher's IV
let IVLength = EVP_CIPHER_iv_length(.make(optional: enc))
let iv = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(IVLength))

let encrypted = UnsafeMutablePointer<UInt8>.allocate(capacity: self.data.count + Int(IVLength))
defer {
#if swift(>=4.1)
ek?.deallocate()
ekPtr.deallocate()
iv.deallocate()
encrypted.deallocate()
#else
ek?.deallocate(capacity: Int(EVP_PKEY_size(.make(optional: key.reference))))
ekPtr.deallocate(capacity: MemoryLayout<UInt8Ptr>.size)
iv.deallocate(capacity: Int(IVLength))
encrypted.deallocate(capacity: self.data.count + Int(IVLength))
#endif
}
var encKeyLength: Int32 = 0
var processedLength: Int32 = 0
var encLength: Int32 = 0
Expand Down Expand Up @@ -505,6 +525,22 @@ public class CryptorRSA {
// Initialize the decryption context.
let rsaDecryptCtx = EVP_CIPHER_CTX_new()
EVP_CIPHER_CTX_init_wrapper(rsaDecryptCtx)
defer {
// On completion deallocate the memory
EVP_CIPHER_CTX_reset_wrapper(rsaDecryptCtx)
EVP_CIPHER_CTX_free_wrapper(rsaDecryptCtx)
}
// get rsaKey
guard let rsaKey = EVP_PKEY_get1_RSA(.make(optional: key.reference)) else {
let source = "Couldn't create key reference from key data"
if let reason = CryptorRSA.getLastError(source: source) {
throw Error(code: ERR_ADD_KEY, reason: reason)
}
throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.")
}
defer {
RSA_free(rsaKey)
}

// Set the additional authenticated data (aad) as the RSA key modulus and publicExponent in an ASN1 sequence.
guard let aad = key.publicKeyBytes else {
Expand Down Expand Up @@ -542,7 +578,6 @@ public class CryptorRSA {
let decrypted = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(encryptedData.count + 16))
defer {
// On completion deallocate the memory
EVP_CIPHER_CTX_free_wrapper(rsaDecryptCtx)
#if swift(>=4.1)
aeskey.deallocate()
decrypted.deallocate()
Expand All @@ -559,7 +594,7 @@ public class CryptorRSA {
let iv = [UInt8](repeating: 0, count: 16)

// Decrypt the encryptedKey into the aeskey using the RSA private key
guard RSA_private_decrypt(Int32(encryptedKey.count), [UInt8](encryptedKey), aeskey, .make(optional: key.reference), RSA_PKCS1_OAEP_PADDING) != 0,
guard RSA_private_decrypt(Int32(encryptedKey.count), [UInt8](encryptedKey), aeskey, rsaKey, RSA_PKCS1_OAEP_PADDING) != 0,
// Set the IV length to be 16 bytes.
EVP_CIPHER_CTX_ctrl(rsaDecryptCtx, EVP_CTRL_GCM_SET_IVLEN, 16, nil) == 1,
// Set the AES key to be 16 bytes.
Expand Down Expand Up @@ -607,23 +642,11 @@ public class CryptorRSA {
/// Decrypt the data using aes GCM for cross platform support.
func decryptedCBC(with key: PrivateKey) throws -> PlaintextData? {
// Convert RSA key to EVP
var evp_key = EVP_PKEY_new()
var status = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference))
guard status == 1 else {
let source = "Couldn't create key reference from key data"
if let reason = CryptorRSA.getLastError(source: source) {

throw Error(code: ERR_ADD_KEY, reason: reason)
}
throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.")
}

// TODO: hash type option is not being used right now.
let encType = EVP_aes_256_cbc()
let padding = RSA_PKCS1_OAEP_PADDING

// Size of symmetric encryption
let encKeyLength = Int(EVP_PKEY_size(evp_key))
let encKeyLength = Int(EVP_PKEY_size(.make(optional: key.reference)))
// Size of the corresponding cipher's IV
let encIVLength = Int(EVP_CIPHER_iv_length(.make(optional: encType)))
// Size of encryptedKey
Expand All @@ -640,7 +663,6 @@ public class CryptorRSA {
defer {
EVP_CIPHER_CTX_reset_wrapper(rsaDecryptCtx)
EVP_CIPHER_CTX_free_wrapper(rsaDecryptCtx)
EVP_PKEY_free(evp_key)
}

EVP_CIPHER_CTX_set_padding(rsaDecryptCtx, padding)
Expand All @@ -651,11 +673,17 @@ public class CryptorRSA {
var decMsgLen: Int32 = 0

let decrypted = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(encryptedData.count + encryptedIV.count))

defer {
#if swift(>=4.1)
decrypted.deallocate()
#else
decrypted.deallocate(capacity: Int(encryptedData.count + encryptedIV.count))
#endif
}
// EVP_OpenInit returns 0 on error or the recovered secret key size if successful
status = encryptedKey.withUnsafeBytes({ (ek: UnsafePointer<UInt8>) -> Int32 in
var status = encryptedKey.withUnsafeBytes({ (ek: UnsafePointer<UInt8>) -> Int32 in
return encryptedIV.withUnsafeBytes({ (iv: UnsafePointer<UInt8>) -> Int32 in
return EVP_OpenInit(rsaDecryptCtx, .make(optional: encType), ek, Int32(encryptedKey.count), iv, evp_key)
return EVP_OpenInit(rsaDecryptCtx, .make(optional: encType), ek, Int32(encryptedKey.count), iv, .make(optional: key.reference))
})
})
guard status != 0 else {
Expand Down Expand Up @@ -723,28 +751,12 @@ public class CryptorRSA {
EVP_MD_CTX_free_wrapper(md_ctx)
}

// convert RSA key to EVP
let evp_key = EVP_PKEY_new()
var rc = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference))
guard rc == 1 else {
let source = "Couldn't create key reference from key data"
if let reason = CryptorRSA.getLastError(source: source) {

throw Error(code: ERR_ADD_KEY, reason: reason)
}
throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.")
}

let (md, padding) = algorithm.algorithmForSignature
let (md, _) = algorithm.algorithmForSignature

// Provide a pkey_ctx to EVP_DigestSignInit so that the EVP_PKEY_CTX of the signing operation
// is written to it, to allow alternative signing options to be set
var pkey_ctx = EVP_PKEY_CTX_new(evp_key, nil)

EVP_DigestSignInit(md_ctx, &pkey_ctx, .make(optional: md), nil, evp_key)

// Now that Init has initialized pkey_ctx, set the padding option
EVP_PKEY_CTX_ctrl(pkey_ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, padding, nil)
EVP_DigestSignInit(md_ctx, nil, .make(optional: md), nil, .make(optional: key.reference))

// Convert Data to UnsafeRawPointer!
_ = self.data.withUnsafeBytes({ (message: UnsafePointer<UInt8>) -> Int32 in
Expand All @@ -756,7 +768,15 @@ public class CryptorRSA {
EVP_DigestSignFinal(md_ctx, nil, &sig_len)
let sig = UnsafeMutablePointer<UInt8>.allocate(capacity: sig_len)

rc = EVP_DigestSignFinal(md_ctx, sig, &sig_len)
defer {
#if swift(>=4.1)
sig.deallocate()
#else
sig.deallocate(capacity: sig_len)
#endif
}

let rc = EVP_DigestSignFinal(md_ctx, sig, &sig_len)
guard rc == 1, sig_len > 0 else {
let source = "Signing failed."
if let reason = CryptorRSA.getLastError(source: source) {
Expand Down Expand Up @@ -824,30 +844,15 @@ public class CryptorRSA {
EVP_MD_CTX_free_wrapper(md_ctx)
}

// convert RSA key to EVP
let evp_key = EVP_PKEY_new()
var rc = EVP_PKEY_set1_RSA(evp_key, .make(optional: key.reference))
guard rc == 1 else {
let source = "Couldn't create key reference from key data"
if let reason = CryptorRSA.getLastError(source: source) {

throw Error(code: ERR_ADD_KEY, reason: reason)
}
throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.")
}

let (md, padding) = algorithm.algorithmForSignature
let (md, _) = algorithm.algorithmForSignature

// Provide a pkey_ctx to EVP_DigestSignInit so that the EVP_PKEY_CTX of the signing operation
// is written to it, to allow alternative signing options to be set
var pkey_ctx = EVP_PKEY_CTX_new(evp_key, nil)

EVP_DigestVerifyInit(md_ctx, &pkey_ctx, .make(optional: md), nil, evp_key)
EVP_DigestVerifyInit(md_ctx, nil, .make(optional: md), nil, .make(optional: key.reference))

// Now that EVP_DigestVerifyInit has initialized pkey_ctx, set the padding option
EVP_PKEY_CTX_ctrl(pkey_ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, padding, nil)

rc = self.data.withUnsafeBytes({ (message: UnsafePointer<UInt8>) -> Int32 in
var rc = self.data.withUnsafeBytes({ (message: UnsafePointer<UInt8>) -> Int32 in
return EVP_DigestUpdate(md_ctx, message, self.data.count)
})
guard rc == 1 else {
Expand Down
24 changes: 7 additions & 17 deletions Sources/CryptorRSA/CryptorRSAKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -362,25 +362,12 @@ extension CryptorRSA {
}

// Extract the certificate's public key data.
let evp_key = X509_get_pubkey(cert)
let evp_key: OpaquePointer? = .init(X509_get_pubkey(cert))
if evp_key == nil {
throw Error(code: ERR_CREATE_CERT_FAILED, reason: "Error getting public key from certificate")
}

let key = EVP_PKEY_get1_RSA( evp_key)
if key == nil {
throw Error(code: ERR_CREATE_CERT_FAILED, reason: "Error getting public key from certificate")
}
defer {
// RSA_free(key)
EVP_PKEY_free(evp_key)
}

#if swift(>=4.1)
return PublicKey(with: .make(optional: key!)!)
#else
return PublicKey(with: key!)
#endif
return PublicKey(with: evp_key)

#else

Expand Down Expand Up @@ -610,6 +597,9 @@ extension CryptorRSA {

#if os(Linux)
var publicKeyBytes: Data?
deinit {
EVP_PKEY_free(.make(optional: reference))
}
#endif

/// Represents the type of key data contained.
Expand Down Expand Up @@ -683,7 +673,7 @@ extension CryptorRSA {
///
/// - Returns: New `RSAKey` instance.
///
internal init(with nativeKey: UnsafeMutablePointer<rsa_st>, type: KeyType) {
internal init(with nativeKey: UnsafeMutablePointer<EVP_PKEY>, type: KeyType) {

self.type = type
self.reference = .make(optional: nativeKey)
Expand Down Expand Up @@ -811,7 +801,7 @@ extension CryptorRSA {
///
/// - Returns: New `RSAKey` instance.
///
public init(with nativeKey: UnsafeMutablePointer<rsa_st>) {
public init(with nativeKey: UnsafeMutablePointer<EVP_PKEY>) {

super.init(with: nativeKey, type: .publicType)
}
Expand Down
17 changes: 1 addition & 16 deletions Sources/CryptorRSA/CryptorRSAUtilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ public extension CryptorRSA {
}

var evp_key: OpaquePointer?

defer {
EVP_PKEY_free(.make(optional: evp_key))
}

// Read in the key data and process depending on key type...
if type == .publicType {
Expand All @@ -88,18 +84,7 @@ public extension CryptorRSA {

evp_key = .init(PEM_read_bio_PrivateKey(bio, nil, nil, nil))
}

let key = EVP_PKEY_get1_RSA(.make(optional: evp_key))
if key == nil {
let source = "Couldn't create key reference from key data"
if let reason = CryptorRSA.getLastError(source: source) {

throw Error(code: ERR_ADD_KEY, reason: reason)
}
throw Error(code: ERR_ADD_KEY, reason: source + ": No OpenSSL error reported.")
}

return .init(key!)
return evp_key
}

///
Expand Down

0 comments on commit f2e3705

Please sign in to comment.