1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <stddef.h> 6 7#include <lib/fdio/debug.h> 8#include <openssl/cipher.h> 9#include <openssl/digest.h> 10#include <openssl/err.h> 11#include <openssl/hkdf.h> 12#include <zircon/errors.h> 13#include <zircon/types.h> 14 15#include "error.h" 16 17#define ZXDEBUG 0 18 19namespace crypto { 20namespace { 21 22zx_status_t MapGlobalErrors(int reason) { 23 switch (reason) { 24 25 case ERR_R_MALLOC_FAILURE: 26 return ZX_ERR_NO_MEMORY; 27 28 case ERR_R_OVERFLOW: 29 return ZX_ERR_OUT_OF_RANGE; 30 31 default: 32 return ZX_ERR_INTERNAL; 33 } 34} 35 36zx_status_t MapCipherErrors(int reason) { 37 switch (reason) { 38 39 case CIPHER_R_CTRL_NOT_IMPLEMENTED: 40 case CIPHER_R_CTRL_OPERATION_NOT_IMPLEMENTED: 41 case CIPHER_R_UNSUPPORTED_KEY_SIZE: 42 case CIPHER_R_UNSUPPORTED_NONCE_SIZE: 43 return ZX_ERR_NOT_SUPPORTED; 44 45 case CIPHER_R_AES_KEY_SETUP_FAILED: 46 case CIPHER_R_INITIALIZATION_ERROR: 47 return ZX_ERR_NO_RESOURCES; 48 49 case CIPHER_R_BAD_KEY_LENGTH: 50 case CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH: 51 case CIPHER_R_INVALID_NONCE: 52 case CIPHER_R_INVALID_NONCE_SIZE: 53 case CIPHER_R_INVALID_OPERATION: 54 case CIPHER_R_INVALID_KEY_LENGTH: 55 case CIPHER_R_INPUT_NOT_INITIALIZED: 56 case CIPHER_R_OUTPUT_ALIASES_INPUT: 57 case CIPHER_R_TAG_TOO_LARGE: 58 case CIPHER_R_TOO_LARGE: 59 return ZX_ERR_INVALID_ARGS; 60 61 case CIPHER_R_NO_CIPHER_SET: 62 case CIPHER_R_NO_DIRECTION_SET: 63 case CIPHER_R_WRONG_FINAL_BLOCK_LENGTH: 64 return ZX_ERR_BAD_STATE; 65 66 case CIPHER_R_BUFFER_TOO_SMALL: 67 return ZX_ERR_BUFFER_TOO_SMALL; 68 69 case CIPHER_R_BAD_DECRYPT: 70 return ZX_ERR_IO_DATA_INTEGRITY; 71 72 default: 73 return MapGlobalErrors(reason); 74 } 75} 76 77zx_status_t MapDigestErrors(int reason) { 78 switch (reason) { 79 80 case DIGEST_R_INPUT_NOT_INITIALIZED: 81 return ZX_ERR_INVALID_ARGS; 82 83 default: 84 return MapGlobalErrors(reason); 85 } 86} 87 88zx_status_t MapHkdfErrors(int reason) { 89 switch (reason) { 90 91 case HKDF_R_OUTPUT_TOO_LARGE: 92 return ZX_ERR_BUFFER_TOO_SMALL; 93 94 default: 95 return MapGlobalErrors(reason); 96 } 97} 98 99// Callback to print BoringSSL's error stack 100int xprintf_crypto_error(const char* str, size_t len, void* ctx) { 101 xprintf(" %s\n", str); 102 return 1; 103} 104 105} // namespace 106 107void xprintf_crypto_errors(zx_status_t* out) { 108 uint32_t packed = ERR_peek_last_error(); 109 xprintf("BoringSSL error(s):\n"); 110 ERR_print_errors_cb(xprintf_crypto_error, nullptr); 111 if (!out) { 112 return; 113 } 114 int lib = ERR_GET_LIB(packed); 115 int reason = ERR_GET_REASON(packed); 116 switch (lib) { 117 case ERR_R_CIPHER_LIB: 118 *out = MapCipherErrors(reason); 119 break; 120 case ERR_R_DIGEST_LIB: 121 *out = MapDigestErrors(reason); 122 break; 123 case ERR_R_HKDF_LIB: 124 *out = MapHkdfErrors(reason); 125 break; 126 default: 127 *out = MapGlobalErrors(reason); 128 break; 129 } 130} 131 132} // namespace crypto 133