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 { 38 unsigned char icv[8], iv[TDES_IVLEN], sha1tmp[SHA_DIGEST_LENGTH]; 39 int rv = -1; 40 41 if (inl < 24) 42 return -1; 43 if (out == NULL) 44 return inl - 16; 45 46 memcpy(ctx->iv, wrap_iv, 8); 47 /* Decrypt first block which will end up as icv */ 48 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 if (out == in) { 55 memmove(out, out + 8, inl - 8); 56 in -= 8; 57 } 58 ctx->hw->cipher(ctx, out, in + 8, inl - 16); 59 /* Decrypt final block which will be IV */ 60 ctx->hw->cipher(ctx, iv, in + inl - 8, 8); 61 /* Reverse order of everything */ 62 BUF_reverse(icv, NULL, 8); 63 BUF_reverse(out, NULL, inl - 16); 64 BUF_reverse(ctx->iv, iv, 8); 65 /* Decrypt again using new IV */ 66 ctx->hw->cipher(ctx, out, out, inl - 16); 67 ctx->hw->cipher(ctx, icv, icv, 8); 68 if (ossl_sha1(out, inl - 16, sha1tmp) /* Work out hash of first portion */ 69 && CRYPTO_memcmp(sha1tmp, icv, 8) == 0) 70 rv = inl - 16; 71 OPENSSL_cleanse(icv, 8); 72 OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH); 73 OPENSSL_cleanse(iv, 8); 74 OPENSSL_cleanse(ctx->iv, sizeof(ctx->iv)); 75 if (rv == -1) 76 OPENSSL_cleanse(out, inl - 16); 77 78 return rv; 79 } 80 81 static int des_ede3_wrap(PROV_CIPHER_CTX *ctx, unsigned char *out, 82 const unsigned char *in, size_t inl) 83 { 84 unsigned char sha1tmp[SHA_DIGEST_LENGTH]; 85 size_t ivlen = TDES_IVLEN; 86 size_t icvlen = TDES_IVLEN; 87 size_t len = inl + ivlen + icvlen; 88 89 if (out == NULL) 90 return len; 91 92 /* Copy input to output buffer + 8 so we have space for IV */ 93 memmove(out + ivlen, in, inl); 94 /* Work out ICV */ 95 if (!ossl_sha1(in, inl, sha1tmp)) 96 return 0; 97 memcpy(out + inl + ivlen, sha1tmp, icvlen); 98 OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH); 99 /* Generate random IV */ 100 if (RAND_bytes_ex(ctx->libctx, ctx->iv, ivlen, 0) <= 0) 101 return 0; 102 memcpy(out, ctx->iv, ivlen); 103 /* Encrypt everything after IV in place */ 104 ctx->hw->cipher(ctx, out + ivlen, out + ivlen, inl + ivlen); 105 BUF_reverse(out, NULL, len); 106 memcpy(ctx->iv, wrap_iv, ivlen); 107 ctx->hw->cipher(ctx, out, out, len); 108 return len; 109 } 110 111 static int tdes_wrap_cipher_internal(PROV_CIPHER_CTX *ctx, unsigned char *out, 112 const unsigned char *in, size_t inl) 113 { 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 if (inl >= EVP_MAXCHUNK || inl % 8) 120 return -1; 121 if (ctx->enc) 122 return des_ede3_wrap(ctx, out, in, inl); 123 else 124 return des_ede3_unwrap(ctx, out, in, inl); 125 } 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 { 131 PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; 132 int ret; 133 134 *outl = 0; 135 if (!ossl_prov_is_running()) 136 return 0; 137 138 if (outsize < inl) { 139 ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); 140 return 0; 141 } 142 143 ret = tdes_wrap_cipher_internal(ctx, out, in, inl); 144 if (ret <= 0) 145 return 0; 146 147 *outl = ret; 148 return 1; 149 } 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 { 155 *outl = 0; 156 if (inl == 0) 157 return 1; 158 if (outsize < inl) { 159 ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); 160 return 0; 161 } 162 163 if (!tdes_wrap_cipher(vctx, out, outl, outsize, in, inl)) { 164 ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); 165 return 0; 166 } 167 return 1; 168 } 169 170 171 # define IMPLEMENT_WRAP_CIPHER(flags, kbits, blkbits, ivbits) \ 172 static OSSL_FUNC_cipher_newctx_fn tdes_wrap_newctx; \ 173 static void *tdes_wrap_newctx(void *provctx) \ 174 { \ 175 return ossl_tdes_newctx(provctx, EVP_CIPH_WRAP_MODE, kbits, blkbits, \ 176 ivbits, flags, \ 177 ossl_prov_cipher_hw_tdes_wrap_cbc()); \ 178 } \ 179 static OSSL_FUNC_cipher_get_params_fn tdes_wrap_get_params; \ 180 static int tdes_wrap_get_params(OSSL_PARAM params[]) \ 181 { \ 182 return ossl_cipher_generic_get_params(params, EVP_CIPH_WRAP_MODE, flags, \ 183 kbits, blkbits, ivbits); \ 184 } \ 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); 211