| // 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, |
| } |
| } |