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