blob: 55683eeec816fb59ff0a9e75b9f036eb5bcfd0ee [file]
// Copyright 2022, The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Error mapping functionality.
use bssl_sys as ffi;
use core::convert::TryFrom;
use kmr_wire::keymint::ErrorCode;
use log::error;
/// Map an OpenSSL `Error` into a KeyMint `ErrorCode` value.
pub(crate) fn map_openssl_err(err: &openssl::error::Error) -> ErrorCode {
let code = err.code();
// Safety: no pointers involved.
let reason = unsafe { ffi::ERR_GET_REASON_RUST(code) };
// Global error reasons.
match reason {
ffi::ERR_R_MALLOC_FAILURE => return ErrorCode::MemoryAllocationFailed,
ffi::ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
| ffi::ERR_R_PASSED_NULL_PARAMETER
| ffi::ERR_R_INTERNAL_ERROR
| ffi::ERR_R_OVERFLOW => return ErrorCode::BoringSslError,
_ => {}
}
// SAFETY: `ERR_GET_LIB` is safe for all inputs.
match unsafe { ffi::ERR_GET_LIB(code) as u32 } {
ffi::ERR_LIB_USER => ErrorCode::try_from(reason).unwrap_or(ErrorCode::BoringSslError),
ffi::ERR_LIB_EVP => translate_evp_error(reason),
ffi::ERR_LIB_ASN1 => translate_asn1_error(reason),
ffi::ERR_LIB_CIPHER => translate_cipher_error(reason),
ffi::ERR_LIB_PKCS8 => translate_pkcs8_error(reason),
ffi::ERR_LIB_X509V3 => translate_x509v3_error(reason),
ffi::ERR_LIB_RSA => translate_rsa_error(reason),
_ => {
error!("unknown BoringSSL error code {}", code);
ErrorCode::BoringSslError
}
}
}
fn translate_evp_error(reason: i32) -> ErrorCode {
match reason {
ffi::EVP_R_UNSUPPORTED_ALGORITHM
| ffi::EVP_R_OPERATON_NOT_INITIALIZED // NOTYPO: upstream typo
| ffi::EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE => ErrorCode::UnsupportedAlgorithm,
ffi::EVP_R_BUFFER_TOO_SMALL
| ffi::EVP_R_EXPECTING_AN_RSA_KEY
| ffi::EVP_R_EXPECTING_A_DSA_KEY
| ffi::EVP_R_MISSING_PARAMETERS => ErrorCode::InvalidKeyBlob,
ffi::EVP_R_DIFFERENT_PARAMETERS | ffi::EVP_R_DECODE_ERROR => ErrorCode::InvalidArgument,
ffi::EVP_R_DIFFERENT_KEY_TYPES => ErrorCode::IncompatibleAlgorithm,
_ => ErrorCode::BoringSslError,
}
}
fn translate_asn1_error(reason: i32) -> ErrorCode {
match reason {
ffi::ASN1_R_ENCODE_ERROR => ErrorCode::InvalidArgument,
_ => ErrorCode::BoringSslError,
}
}
fn translate_cipher_error(reason: i32) -> ErrorCode {
match reason {
ffi::CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH
| ffi::CIPHER_R_WRONG_FINAL_BLOCK_LENGTH => ErrorCode::InvalidInputLength,
ffi::CIPHER_R_UNSUPPORTED_KEY_SIZE | ffi::CIPHER_R_BAD_KEY_LENGTH => {
ErrorCode::UnsupportedKeySize
}
ffi::CIPHER_R_BAD_DECRYPT => ErrorCode::InvalidArgument,
ffi::CIPHER_R_INVALID_KEY_LENGTH => ErrorCode::InvalidKeyBlob,
_ => ErrorCode::BoringSslError,
}
}
fn translate_pkcs8_error(reason: i32) -> ErrorCode {
match reason {
ffi::PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM | ffi::PKCS8_R_UNKNOWN_CIPHER => {
ErrorCode::UnsupportedAlgorithm
}
ffi::PKCS8_R_PRIVATE_KEY_ENCODE_ERROR | ffi::PKCS8_R_PRIVATE_KEY_DECODE_ERROR => {
ErrorCode::InvalidKeyBlob
}
ffi::PKCS8_R_ENCODE_ERROR => ErrorCode::InvalidArgument,
_ => ErrorCode::BoringSslError,
}
}
fn translate_x509v3_error(reason: i32) -> ErrorCode {
match reason {
ffi::X509V3_R_UNKNOWN_OPTION => ErrorCode::UnsupportedAlgorithm,
_ => ErrorCode::BoringSslError,
}
}
fn translate_rsa_error(reason: i32) -> ErrorCode {
match reason {
ffi::RSA_R_KEY_SIZE_TOO_SMALL => ErrorCode::IncompatiblePaddingMode,
ffi::RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE | ffi::RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE => {
ErrorCode::InvalidInputLength
}
ffi::RSA_R_DATA_TOO_LARGE_FOR_MODULUS | ffi::RSA_R_DATA_TOO_LARGE => {
ErrorCode::InvalidArgument
}
_ => ErrorCode::BoringSslError,
}
}