/src/openssl30/providers/implementations/ciphers/cipher_tdes_wrap.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * |
4 | | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5 | | * this file except in compliance with the License. You can obtain a copy |
6 | | * in the file LICENSE in the source distribution or at |
7 | | * https://www.openssl.org/source/license.html |
8 | | */ |
9 | | |
10 | | /* |
11 | | * DES and SHA-1 low level APIs are deprecated for public use, but still ok for |
12 | | * internal use. |
13 | | */ |
14 | | #include "internal/deprecated.h" |
15 | | |
16 | | #include <openssl/sha.h> |
17 | | #include <openssl/rand.h> |
18 | | #include <openssl/proverr.h> |
19 | | #include "cipher_tdes_default.h" |
20 | | #include "crypto/evp.h" |
21 | | #include "crypto/sha.h" |
22 | | #include "prov/implementations.h" |
23 | | #include "prov/providercommon.h" |
24 | | |
25 | | #define TDES_WRAP_FLAGS PROV_CIPHER_FLAG_CUSTOM_IV | PROV_CIPHER_FLAG_RAND_KEY |
26 | | |
27 | | static OSSL_FUNC_cipher_update_fn tdes_wrap_update; |
28 | | static OSSL_FUNC_cipher_cipher_fn tdes_wrap_cipher; |
29 | | |
30 | | static const unsigned char wrap_iv[8] = |
31 | | { |
32 | | 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05 |
33 | | }; |
34 | | |
35 | | static int des_ede3_unwrap(PROV_CIPHER_CTX *ctx, unsigned char *out, |
36 | | const unsigned char *in, size_t inl) |
37 | 0 | { |
38 | 0 | unsigned char icv[8], iv[TDES_IVLEN], sha1tmp[SHA_DIGEST_LENGTH]; |
39 | 0 | int rv = -1; |
40 | |
|
41 | 0 | if (inl < 24) |
42 | 0 | return -1; |
43 | 0 | if (out == NULL) |
44 | 0 | return inl - 16; |
45 | | |
46 | 0 | memcpy(ctx->iv, wrap_iv, 8); |
47 | | /* Decrypt first block which will end up as icv */ |
48 | 0 | ctx->hw->cipher(ctx, icv, in, 8); |
49 | | /* Decrypt central blocks */ |
50 | | /* |
51 | | * If decrypting in place move whole output along a block so the next |
52 | | * des_ede_cbc_cipher is in place. |
53 | | */ |
54 | 0 | if (out == in) { |
55 | 0 | memmove(out, out + 8, inl - 8); |
56 | 0 | in -= 8; |
57 | 0 | } |
58 | 0 | ctx->hw->cipher(ctx, out, in + 8, inl - 16); |
59 | | /* Decrypt final block which will be IV */ |
60 | 0 | ctx->hw->cipher(ctx, iv, in + inl - 8, 8); |
61 | | /* Reverse order of everything */ |
62 | 0 | BUF_reverse(icv, NULL, 8); |
63 | 0 | BUF_reverse(out, NULL, inl - 16); |
64 | 0 | BUF_reverse(ctx->iv, iv, 8); |
65 | | /* Decrypt again using new IV */ |
66 | 0 | ctx->hw->cipher(ctx, out, out, inl - 16); |
67 | 0 | ctx->hw->cipher(ctx, icv, icv, 8); |
68 | 0 | if (ossl_sha1(out, inl - 16, sha1tmp) /* Work out hash of first portion */ |
69 | 0 | && CRYPTO_memcmp(sha1tmp, icv, 8) == 0) |
70 | 0 | rv = inl - 16; |
71 | 0 | OPENSSL_cleanse(icv, 8); |
72 | 0 | OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH); |
73 | 0 | OPENSSL_cleanse(iv, 8); |
74 | 0 | OPENSSL_cleanse(ctx->iv, sizeof(ctx->iv)); |
75 | 0 | if (rv == -1) |
76 | 0 | OPENSSL_cleanse(out, inl - 16); |
77 | |
|
78 | 0 | return rv; |
79 | 0 | } |
80 | | |
81 | | static int des_ede3_wrap(PROV_CIPHER_CTX *ctx, unsigned char *out, |
82 | | const unsigned char *in, size_t inl) |
83 | 0 | { |
84 | 0 | unsigned char sha1tmp[SHA_DIGEST_LENGTH]; |
85 | 0 | size_t ivlen = TDES_IVLEN; |
86 | 0 | size_t icvlen = TDES_IVLEN; |
87 | 0 | size_t len = inl + ivlen + icvlen; |
88 | |
|
89 | 0 | if (out == NULL) |
90 | 0 | return len; |
91 | | |
92 | | /* Copy input to output buffer + 8 so we have space for IV */ |
93 | 0 | memmove(out + ivlen, in, inl); |
94 | | /* Work out ICV */ |
95 | 0 | if (!ossl_sha1(in, inl, sha1tmp)) |
96 | 0 | return 0; |
97 | 0 | memcpy(out + inl + ivlen, sha1tmp, icvlen); |
98 | 0 | OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH); |
99 | | /* Generate random IV */ |
100 | 0 | if (RAND_bytes_ex(ctx->libctx, ctx->iv, ivlen, 0) <= 0) |
101 | 0 | return 0; |
102 | 0 | memcpy(out, ctx->iv, ivlen); |
103 | | /* Encrypt everything after IV in place */ |
104 | 0 | ctx->hw->cipher(ctx, out + ivlen, out + ivlen, inl + ivlen); |
105 | 0 | BUF_reverse(out, NULL, len); |
106 | 0 | memcpy(ctx->iv, wrap_iv, ivlen); |
107 | 0 | ctx->hw->cipher(ctx, out, out, len); |
108 | 0 | return len; |
109 | 0 | } |
110 | | |
111 | | static int tdes_wrap_cipher_internal(PROV_CIPHER_CTX *ctx, unsigned char *out, |
112 | | const unsigned char *in, size_t inl) |
113 | 0 | { |
114 | | /* |
115 | | * Sanity check input length: we typically only wrap keys so EVP_MAXCHUNK |
116 | | * is more than will ever be needed. Also input length must be a multiple |
117 | | * of 8 bits. |
118 | | */ |
119 | 0 | if (inl >= EVP_MAXCHUNK || inl % 8) |
120 | 0 | return -1; |
121 | 0 | if (ctx->enc) |
122 | 0 | return des_ede3_wrap(ctx, out, in, inl); |
123 | 0 | else |
124 | 0 | return des_ede3_unwrap(ctx, out, in, inl); |
125 | 0 | } |
126 | | |
127 | | static int tdes_wrap_cipher(void *vctx, |
128 | | unsigned char *out, size_t *outl, size_t outsize, |
129 | | const unsigned char *in, size_t inl) |
130 | 0 | { |
131 | 0 | PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; |
132 | 0 | int ret; |
133 | |
|
134 | 0 | *outl = 0; |
135 | 0 | if (!ossl_prov_is_running()) |
136 | 0 | return 0; |
137 | | |
138 | 0 | if (outsize < inl) { |
139 | 0 | ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); |
140 | 0 | return 0; |
141 | 0 | } |
142 | | |
143 | 0 | ret = tdes_wrap_cipher_internal(ctx, out, in, inl); |
144 | 0 | if (ret <= 0) |
145 | 0 | return 0; |
146 | | |
147 | 0 | *outl = ret; |
148 | 0 | return 1; |
149 | 0 | } |
150 | | |
151 | | static int tdes_wrap_update(void *vctx, unsigned char *out, size_t *outl, |
152 | | size_t outsize, const unsigned char *in, |
153 | | size_t inl) |
154 | 0 | { |
155 | 0 | *outl = 0; |
156 | 0 | if (inl == 0) |
157 | 0 | return 1; |
158 | 0 | if (outsize < inl) { |
159 | 0 | ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); |
160 | 0 | return 0; |
161 | 0 | } |
162 | | |
163 | 0 | if (!tdes_wrap_cipher(vctx, out, outl, outsize, in, inl)) { |
164 | 0 | ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); |
165 | 0 | return 0; |
166 | 0 | } |
167 | 0 | return 1; |
168 | 0 | } |
169 | | |
170 | | |
171 | | # define IMPLEMENT_WRAP_CIPHER(flags, kbits, blkbits, ivbits) \ |
172 | | static OSSL_FUNC_cipher_newctx_fn tdes_wrap_newctx; \ |
173 | 0 | static void *tdes_wrap_newctx(void *provctx) \ |
174 | 0 | { \ |
175 | 0 | return ossl_tdes_newctx(provctx, EVP_CIPH_WRAP_MODE, kbits, blkbits, \ |
176 | 0 | ivbits, flags, \ |
177 | 0 | ossl_prov_cipher_hw_tdes_wrap_cbc()); \ |
178 | 0 | } \ |
179 | | static OSSL_FUNC_cipher_get_params_fn tdes_wrap_get_params; \ |
180 | 25 | static int tdes_wrap_get_params(OSSL_PARAM params[]) \ |
181 | 25 | { \ |
182 | 25 | return ossl_cipher_generic_get_params(params, EVP_CIPH_WRAP_MODE, flags, \ |
183 | 25 | kbits, blkbits, ivbits); \ |
184 | 25 | } \ |
185 | | const OSSL_DISPATCH ossl_tdes_wrap_cbc_functions[] = \ |
186 | | { \ |
187 | | { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void)) ossl_tdes_einit }, \ |
188 | | { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void)) ossl_tdes_dinit }, \ |
189 | | { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))tdes_wrap_cipher }, \ |
190 | | { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))tdes_wrap_newctx }, \ |
191 | | { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))ossl_tdes_freectx }, \ |
192 | | { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))tdes_wrap_update }, \ |
193 | | { OSSL_FUNC_CIPHER_FINAL, \ |
194 | | (void (*)(void))ossl_cipher_generic_stream_final }, \ |
195 | | { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))tdes_wrap_get_params }, \ |
196 | | { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ |
197 | | (void (*)(void))ossl_cipher_generic_gettable_params }, \ |
198 | | { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ |
199 | | (void (*)(void))ossl_tdes_get_ctx_params }, \ |
200 | | { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ |
201 | | (void (*)(void))ossl_tdes_gettable_ctx_params }, \ |
202 | | { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ |
203 | | (void (*)(void))ossl_cipher_generic_set_ctx_params }, \ |
204 | | { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ |
205 | | (void (*)(void))ossl_cipher_generic_settable_ctx_params }, \ |
206 | | { 0, NULL } \ |
207 | | } |
208 | | |
209 | | /* ossl_tdes_wrap_cbc_functions */ |
210 | | IMPLEMENT_WRAP_CIPHER(TDES_WRAP_FLAGS, 64*3, 64, 0); |