Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EVP_CMAC_init fails but no errors #220

Open
thomzon opened this issue Jul 26, 2024 · 1 comment
Open

EVP_CMAC_init fails but no errors #220

thomzon opened this issue Jul 26, 2024 · 1 comment

Comments

@thomzon
Copy link

thomzon commented Jul 26, 2024

Hi,

I'm trying to use migrate a CMAC function from OpenSSL 1 to 3, going from the deprecated CMAC API to the EVP_MAC API.
Unfortunately I am stuck, I cannot make the EVP_MAC_init call to work. I've tried many different combinations, without success, it always returns 0. Also, ERR_get_error returns 0, so something fails but apparently without adding anything to the error stack.

Here is the function, maybe I'm doing something obviously wrong? Or can there be an issue elsewhere?

    static func generateAESCMAC(key: [UInt8], message: [UInt8] ) throws -> [UInt8] {
        guard let lib = OSSL_LIB_CTX_new()
        else {
            throw OpenSSLError.cmac("Cannot setup lib ctx")
        }
        defer { OSSL_LIB_CTX_free(lib) }
        
        guard let macAlgo = EVP_MAC_fetch(lib, "CMAC", nil)
        else {
            throw OpenSSLError.cmac("Cannot fetch CMAC algo")
        }
        defer { EVP_MAC_free(macAlgo) }

        guard let ctx = EVP_MAC_CTX_new(macAlgo)
        else {
            throw OpenSSLError.cmac("Cannot create CMAC ctx")
        }
        defer { EVP_MAC_CTX_free(ctx) }

        var params: [OSSL_PARAM] = []
        var cipherString = "aes-128-cbc".cString(using: .utf8)!
        let cipherParam = OSSL_PARAM_construct_utf8_string(
            OSSL_MAC_PARAM_CIPHER,
            &cipherString,
            0
        )
        params.append(cipherParam)
        params.append(OSSL_PARAM_construct_end())
        var keyValue = key
        guard EVP_MAC_init(ctx, &keyValue, key.count, params) == 1
        else {
            throw OpenSSLError.cmac("Cannot init CMAC")
        }
        
        guard EVP_MAC_update(ctx, message, message.count) == 1
        else {
            throw OpenSSLError.cmac("Cannot update CMAC")
        }
        
        var cmacResult = [UInt8](repeating: 0, count: Int(EVP_MAX_MD_SIZE))
        var cmacLength: size_t = 0
        guard EVP_MAC_final(ctx, &cmacResult, &cmacLength, cmacResult.count) == 1
        else {
            throw OpenSSLError.cmac("Cannot final CMAC")
        }
        
        return Array(cmacResult[0..<cmacLength])
    }
@thomzon
Copy link
Author

thomzon commented Aug 16, 2024

Found the solution, handling of the OSSL_PARAM was not OK memory wise, resulting in an invalid OSSL_PARAM. That does not explain why the init call never generated an error, it should probably have when called with an invalid parameter list.

The following code works:

    static func generateAESCMAC(key: [UInt8], message: [UInt8]) throws -> [UInt8] {
        guard let lib = OSSL_LIB_CTX_new()
        else {
            throw OpenSSLError.cmac("Cannot setup lib ctx")
        }
        defer { OSSL_LIB_CTX_free(lib) }
        
        guard let macAlgo = EVP_MAC_fetch(lib, "CMAC", nil)
        else {
            throw OpenSSLError.cmac("Cannot fetch CMAC algo")
        }
        defer { EVP_MAC_free(macAlgo) }

        guard let ctx = EVP_MAC_CTX_new(macAlgo)
        else {
            throw OpenSSLError.cmac("Cannot create CMAC ctx")
        }
        defer { EVP_MAC_CTX_free(ctx) }

        var cipherString = "AES-128-CBC".cString(using: .utf8)!
        try OSSL_MAC_PARAM_CIPHER.withCString { cipherKey in
            try cipherString.withUnsafeMutableBytes { cipherBytes in
                let cipherParam = OSSL_PARAM_construct_utf8_string(
                    cipherKey,
                    cipherBytes.baseAddress,
                    0
                )
                let params = [cipherParam, OSSL_PARAM_construct_end()]
                guard EVP_MAC_init(ctx, key, key.count, params) == 1
                else {
                    throw OpenSSLError.cmac("Cannot init CMAC")
                }
            }
        }
                
        guard EVP_MAC_update(ctx, message, message.count) == 1
        else {
            throw OpenSSLError.cmac("Cannot update CMAC")
        }
        
        var cmacResult = [UInt8](repeating: 0, count: Int(EVP_MAX_MD_SIZE))
        var cmacLength: size_t = 0
        
        if EVP_MAC_final(ctx, &cmacResult, &cmacLength, cmacResult.count) == 1 {
            return Array(cmacResult[0..<cmacLength])
        } else {
            throw OpenSSLError.cmac("Cannot final CMAC")
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant