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 low level APIs are deprecated for public use, but still ok for internal 12 * use. 13 */ 14 #include "internal/deprecated.h" 15 16 #include "prov/ciphercommon.h" 17 #include "cipher_des.h" 18 19 static int cipher_hw_des_initkey(PROV_CIPHER_CTX *ctx, 20 const unsigned char *key, size_t keylen) 21 { 22 PROV_DES_CTX *dctx = (PROV_DES_CTX *)ctx; 23 DES_cblock *deskey = (DES_cblock *)key; 24 DES_key_schedule *ks = &dctx->dks.ks; 25 26 dctx->dstream.cbc = NULL; 27 #if defined(SPARC_DES_CAPABLE) 28 if (SPARC_DES_CAPABLE) { 29 if (ctx->mode == EVP_CIPH_CBC_MODE) { 30 des_t4_key_expand(&deskey[0], ks); 31 dctx->dstream.cbc = ctx->enc ? des_t4_cbc_encrypt : 32 des_t4_cbc_decrypt; 33 return 1; 34 } 35 } 36 #endif 37 DES_set_key_unchecked(deskey, ks); 38 return 1; 39 } 40 41 static void cipher_hw_des_copyctx(PROV_CIPHER_CTX *dst, 42 const PROV_CIPHER_CTX *src) 43 { 44 PROV_DES_CTX *sctx = (PROV_DES_CTX *)src; 45 PROV_DES_CTX *dctx = (PROV_DES_CTX *)dst; 46 47 *dctx = *sctx; 48 dst->ks = &dctx->dks.ks; 49 } 50 51 static int cipher_hw_des_ecb_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out, 52 const unsigned char *in, size_t len) 53 { 54 size_t i, bl = ctx->blocksize; 55 DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks); 56 57 if (len < bl) 58 return 1; 59 for (i = 0, len -= bl; i <= len; i += bl) 60 DES_ecb_encrypt((const_DES_cblock *)(in + i), 61 (const_DES_cblock *)(out + i), key, ctx->enc); 62 return 1; 63 } 64 65 static int cipher_hw_des_cbc_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out, 66 const unsigned char *in, size_t len) 67 { 68 PROV_DES_CTX *dctx = (PROV_DES_CTX *)ctx; 69 DES_key_schedule *key = &(dctx->dks.ks); 70 71 if (dctx->dstream.cbc != NULL) { 72 (*dctx->dstream.cbc) (in, out, len, key, ctx->iv); 73 return 1; 74 } 75 76 while (len >= MAXCHUNK) { 77 DES_ncbc_encrypt(in, out, MAXCHUNK, key, (DES_cblock *)ctx->iv, 78 ctx->enc); 79 len -= MAXCHUNK; 80 in += MAXCHUNK; 81 out += MAXCHUNK; 82 } 83 if (len > 0) 84 DES_ncbc_encrypt(in, out, (long)len, key, (DES_cblock *)ctx->iv, 85 ctx->enc); 86 return 1; 87 } 88 89 static int cipher_hw_des_ofb64_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out, 90 const unsigned char *in, size_t len) 91 { 92 int num = ctx->num; 93 DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks); 94 95 while (len >= MAXCHUNK) { 96 DES_ofb64_encrypt(in, out, MAXCHUNK, key, (DES_cblock *)ctx->iv, &num); 97 len -= MAXCHUNK; 98 in += MAXCHUNK; 99 out += MAXCHUNK; 100 } 101 if (len > 0) { 102 DES_ofb64_encrypt(in, out, (long)len, key, (DES_cblock *)ctx->iv, &num); 103 } 104 ctx->num = num; 105 return 1; 106 } 107 108 static int cipher_hw_des_cfb64_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out, 109 const unsigned char *in, size_t len) 110 { 111 size_t chunk = MAXCHUNK; 112 DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks); 113 int num = ctx->num; 114 115 if (len < chunk) 116 chunk = len; 117 while (len > 0 && len >= chunk) { 118 DES_cfb64_encrypt(in, out, (long)chunk, key, (DES_cblock *)ctx->iv, 119 &num, ctx->enc); 120 len -= chunk; 121 in += chunk; 122 out += chunk; 123 if (len < chunk) 124 chunk = len; 125 } 126 ctx->num = num; 127 return 1; 128 } 129 130 /* 131 * Although we have a CFB-r implementation for DES, it doesn't pack the right 132 * way, so wrap it here 133 */ 134 static int cipher_hw_des_cfb1_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out, 135 const unsigned char *in, size_t inl) 136 { 137 size_t n, chunk = MAXCHUNK / 8; 138 DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks); 139 unsigned char c[1], d[1]; 140 141 if (inl < chunk) 142 chunk = inl; 143 144 while (inl && inl >= chunk) { 145 for (n = 0; n < chunk * 8; ++n) { 146 c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0; 147 DES_cfb_encrypt(c, d, 1, 1, key, (DES_cblock *)ctx->iv, ctx->enc); 148 out[n / 8] = 149 (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8))) | 150 ((d[0] & 0x80) >> (unsigned int)(n % 8)); 151 } 152 inl -= chunk; 153 in += chunk; 154 out += chunk; 155 if (inl < chunk) 156 chunk = inl; 157 } 158 159 return 1; 160 } 161 162 static int cipher_hw_des_cfb8_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out, 163 const unsigned char *in, size_t inl) 164 { 165 DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks); 166 167 while (inl >= MAXCHUNK) { 168 DES_cfb_encrypt(in, out, 8, (long)MAXCHUNK, key, 169 (DES_cblock *)ctx->iv, ctx->enc); 170 inl -= MAXCHUNK; 171 in += MAXCHUNK; 172 out += MAXCHUNK; 173 } 174 if (inl > 0) 175 DES_cfb_encrypt(in, out, 8, (long)inl, key, 176 (DES_cblock *)ctx->iv, ctx->enc); 177 return 1; 178 } 179 180 #define PROV_CIPHER_HW_des_mode(mode) \ 181 static const PROV_CIPHER_HW des_##mode = { \ 182 cipher_hw_des_initkey, \ 183 cipher_hw_des_##mode##_cipher, \ 184 cipher_hw_des_copyctx \ 185 }; \ 186 const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_##mode(void) \ 187 { \ 188 return &des_##mode; \ 189 } 190 191 PROV_CIPHER_HW_des_mode(ecb) 192 PROV_CIPHER_HW_des_mode(cbc) 193 PROV_CIPHER_HW_des_mode(ofb64) 194 PROV_CIPHER_HW_des_mode(cfb64) 195 PROV_CIPHER_HW_des_mode(cfb1) 196 PROV_CIPHER_HW_des_mode(cfb8) 197