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