1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* 11e1051a39Sopenharmony_ci * DES low level APIs are deprecated for public use, but still ok for internal 12e1051a39Sopenharmony_ci * use. 13e1051a39Sopenharmony_ci */ 14e1051a39Sopenharmony_ci#include "internal/deprecated.h" 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci#include <openssl/crypto.h> 17e1051a39Sopenharmony_ci#include "des_local.h" 18e1051a39Sopenharmony_ci#include "spr.h" 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_civoid DES_encrypt1(DES_LONG *data, DES_key_schedule *ks, int enc) 21e1051a39Sopenharmony_ci{ 22e1051a39Sopenharmony_ci register DES_LONG l, r, t, u; 23e1051a39Sopenharmony_ci register DES_LONG *s; 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ci r = data[0]; 26e1051a39Sopenharmony_ci l = data[1]; 27e1051a39Sopenharmony_ci 28e1051a39Sopenharmony_ci IP(r, l); 29e1051a39Sopenharmony_ci /* 30e1051a39Sopenharmony_ci * Things have been modified so that the initial rotate is done outside 31e1051a39Sopenharmony_ci * the loop. This required the DES_SPtrans values in sp.h to be rotated 32e1051a39Sopenharmony_ci * 1 bit to the right. One perl script later and things have a 5% speed 33e1051a39Sopenharmony_ci * up on a sparc2. Thanks to Richard Outerbridge for pointing this out. 34e1051a39Sopenharmony_ci */ 35e1051a39Sopenharmony_ci /* clear the top bits on machines with 8byte longs */ 36e1051a39Sopenharmony_ci /* shift left by 2 */ 37e1051a39Sopenharmony_ci r = ROTATE(r, 29) & 0xffffffffL; 38e1051a39Sopenharmony_ci l = ROTATE(l, 29) & 0xffffffffL; 39e1051a39Sopenharmony_ci 40e1051a39Sopenharmony_ci s = ks->ks->deslong; 41e1051a39Sopenharmony_ci /* 42e1051a39Sopenharmony_ci * I don't know if it is worth the effort of loop unrolling the inner 43e1051a39Sopenharmony_ci * loop 44e1051a39Sopenharmony_ci */ 45e1051a39Sopenharmony_ci if (enc) { 46e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 0); /* 1 */ 47e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 2); /* 2 */ 48e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 4); /* 3 */ 49e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 6); /* 4 */ 50e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 8); /* 5 */ 51e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 10); /* 6 */ 52e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 12); /* 7 */ 53e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 14); /* 8 */ 54e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 16); /* 9 */ 55e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 18); /* 10 */ 56e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 20); /* 11 */ 57e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 22); /* 12 */ 58e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 24); /* 13 */ 59e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 26); /* 14 */ 60e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 28); /* 15 */ 61e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 30); /* 16 */ 62e1051a39Sopenharmony_ci } else { 63e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 30); /* 16 */ 64e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 28); /* 15 */ 65e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 26); /* 14 */ 66e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 24); /* 13 */ 67e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 22); /* 12 */ 68e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 20); /* 11 */ 69e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 18); /* 10 */ 70e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 16); /* 9 */ 71e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 14); /* 8 */ 72e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 12); /* 7 */ 73e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 10); /* 6 */ 74e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 8); /* 5 */ 75e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 6); /* 4 */ 76e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 4); /* 3 */ 77e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 2); /* 2 */ 78e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 0); /* 1 */ 79e1051a39Sopenharmony_ci } 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_ci /* rotate and clear the top bits on machines with 8byte longs */ 82e1051a39Sopenharmony_ci l = ROTATE(l, 3) & 0xffffffffL; 83e1051a39Sopenharmony_ci r = ROTATE(r, 3) & 0xffffffffL; 84e1051a39Sopenharmony_ci 85e1051a39Sopenharmony_ci FP(r, l); 86e1051a39Sopenharmony_ci data[0] = l; 87e1051a39Sopenharmony_ci data[1] = r; 88e1051a39Sopenharmony_ci l = r = t = u = 0; 89e1051a39Sopenharmony_ci} 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_civoid DES_encrypt2(DES_LONG *data, DES_key_schedule *ks, int enc) 92e1051a39Sopenharmony_ci{ 93e1051a39Sopenharmony_ci register DES_LONG l, r, t, u; 94e1051a39Sopenharmony_ci register DES_LONG *s; 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_ci r = data[0]; 97e1051a39Sopenharmony_ci l = data[1]; 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_ci /* 100e1051a39Sopenharmony_ci * Things have been modified so that the initial rotate is done outside 101e1051a39Sopenharmony_ci * the loop. This required the DES_SPtrans values in sp.h to be rotated 102e1051a39Sopenharmony_ci * 1 bit to the right. One perl script later and things have a 5% speed 103e1051a39Sopenharmony_ci * up on a sparc2. Thanks to Richard Outerbridge for pointing this out. 104e1051a39Sopenharmony_ci */ 105e1051a39Sopenharmony_ci /* clear the top bits on machines with 8byte longs */ 106e1051a39Sopenharmony_ci r = ROTATE(r, 29) & 0xffffffffL; 107e1051a39Sopenharmony_ci l = ROTATE(l, 29) & 0xffffffffL; 108e1051a39Sopenharmony_ci 109e1051a39Sopenharmony_ci s = ks->ks->deslong; 110e1051a39Sopenharmony_ci /* 111e1051a39Sopenharmony_ci * I don't know if it is worth the effort of loop unrolling the inner 112e1051a39Sopenharmony_ci * loop 113e1051a39Sopenharmony_ci */ 114e1051a39Sopenharmony_ci if (enc) { 115e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 0); /* 1 */ 116e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 2); /* 2 */ 117e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 4); /* 3 */ 118e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 6); /* 4 */ 119e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 8); /* 5 */ 120e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 10); /* 6 */ 121e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 12); /* 7 */ 122e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 14); /* 8 */ 123e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 16); /* 9 */ 124e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 18); /* 10 */ 125e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 20); /* 11 */ 126e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 22); /* 12 */ 127e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 24); /* 13 */ 128e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 26); /* 14 */ 129e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 28); /* 15 */ 130e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 30); /* 16 */ 131e1051a39Sopenharmony_ci } else { 132e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 30); /* 16 */ 133e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 28); /* 15 */ 134e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 26); /* 14 */ 135e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 24); /* 13 */ 136e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 22); /* 12 */ 137e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 20); /* 11 */ 138e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 18); /* 10 */ 139e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 16); /* 9 */ 140e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 14); /* 8 */ 141e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 12); /* 7 */ 142e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 10); /* 6 */ 143e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 8); /* 5 */ 144e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 6); /* 4 */ 145e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 4); /* 3 */ 146e1051a39Sopenharmony_ci D_ENCRYPT(l, r, 2); /* 2 */ 147e1051a39Sopenharmony_ci D_ENCRYPT(r, l, 0); /* 1 */ 148e1051a39Sopenharmony_ci } 149e1051a39Sopenharmony_ci /* rotate and clear the top bits on machines with 8byte longs */ 150e1051a39Sopenharmony_ci data[0] = ROTATE(l, 3) & 0xffffffffL; 151e1051a39Sopenharmony_ci data[1] = ROTATE(r, 3) & 0xffffffffL; 152e1051a39Sopenharmony_ci l = r = t = u = 0; 153e1051a39Sopenharmony_ci} 154e1051a39Sopenharmony_ci 155e1051a39Sopenharmony_civoid DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1, 156e1051a39Sopenharmony_ci DES_key_schedule *ks2, DES_key_schedule *ks3) 157e1051a39Sopenharmony_ci{ 158e1051a39Sopenharmony_ci register DES_LONG l, r; 159e1051a39Sopenharmony_ci 160e1051a39Sopenharmony_ci l = data[0]; 161e1051a39Sopenharmony_ci r = data[1]; 162e1051a39Sopenharmony_ci IP(l, r); 163e1051a39Sopenharmony_ci data[0] = l; 164e1051a39Sopenharmony_ci data[1] = r; 165e1051a39Sopenharmony_ci DES_encrypt2((DES_LONG *)data, ks1, DES_ENCRYPT); 166e1051a39Sopenharmony_ci DES_encrypt2((DES_LONG *)data, ks2, DES_DECRYPT); 167e1051a39Sopenharmony_ci DES_encrypt2((DES_LONG *)data, ks3, DES_ENCRYPT); 168e1051a39Sopenharmony_ci l = data[0]; 169e1051a39Sopenharmony_ci r = data[1]; 170e1051a39Sopenharmony_ci FP(r, l); 171e1051a39Sopenharmony_ci data[0] = l; 172e1051a39Sopenharmony_ci data[1] = r; 173e1051a39Sopenharmony_ci} 174e1051a39Sopenharmony_ci 175e1051a39Sopenharmony_civoid DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1, 176e1051a39Sopenharmony_ci DES_key_schedule *ks2, DES_key_schedule *ks3) 177e1051a39Sopenharmony_ci{ 178e1051a39Sopenharmony_ci register DES_LONG l, r; 179e1051a39Sopenharmony_ci 180e1051a39Sopenharmony_ci l = data[0]; 181e1051a39Sopenharmony_ci r = data[1]; 182e1051a39Sopenharmony_ci IP(l, r); 183e1051a39Sopenharmony_ci data[0] = l; 184e1051a39Sopenharmony_ci data[1] = r; 185e1051a39Sopenharmony_ci DES_encrypt2((DES_LONG *)data, ks3, DES_DECRYPT); 186e1051a39Sopenharmony_ci DES_encrypt2((DES_LONG *)data, ks2, DES_ENCRYPT); 187e1051a39Sopenharmony_ci DES_encrypt2((DES_LONG *)data, ks1, DES_DECRYPT); 188e1051a39Sopenharmony_ci l = data[0]; 189e1051a39Sopenharmony_ci r = data[1]; 190e1051a39Sopenharmony_ci FP(r, l); 191e1051a39Sopenharmony_ci data[0] = l; 192e1051a39Sopenharmony_ci data[1] = r; 193e1051a39Sopenharmony_ci} 194e1051a39Sopenharmony_ci 195e1051a39Sopenharmony_ci#ifndef DES_DEFAULT_OPTIONS 196e1051a39Sopenharmony_ci 197e1051a39Sopenharmony_ci# undef CBC_ENC_C__DONT_UPDATE_IV 198e1051a39Sopenharmony_ci# include "ncbc_enc.c" /* DES_ncbc_encrypt */ 199e1051a39Sopenharmony_ci 200e1051a39Sopenharmony_civoid DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output, 201e1051a39Sopenharmony_ci long length, DES_key_schedule *ks1, 202e1051a39Sopenharmony_ci DES_key_schedule *ks2, DES_key_schedule *ks3, 203e1051a39Sopenharmony_ci DES_cblock *ivec, int enc) 204e1051a39Sopenharmony_ci{ 205e1051a39Sopenharmony_ci register DES_LONG tin0, tin1; 206e1051a39Sopenharmony_ci register DES_LONG tout0, tout1, xor0, xor1; 207e1051a39Sopenharmony_ci register const unsigned char *in; 208e1051a39Sopenharmony_ci unsigned char *out; 209e1051a39Sopenharmony_ci register long l = length; 210e1051a39Sopenharmony_ci DES_LONG tin[2]; 211e1051a39Sopenharmony_ci unsigned char *iv; 212e1051a39Sopenharmony_ci 213e1051a39Sopenharmony_ci in = input; 214e1051a39Sopenharmony_ci out = output; 215e1051a39Sopenharmony_ci iv = &(*ivec)[0]; 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_ci if (enc) { 218e1051a39Sopenharmony_ci c2l(iv, tout0); 219e1051a39Sopenharmony_ci c2l(iv, tout1); 220e1051a39Sopenharmony_ci for (l -= 8; l >= 0; l -= 8) { 221e1051a39Sopenharmony_ci c2l(in, tin0); 222e1051a39Sopenharmony_ci c2l(in, tin1); 223e1051a39Sopenharmony_ci tin0 ^= tout0; 224e1051a39Sopenharmony_ci tin1 ^= tout1; 225e1051a39Sopenharmony_ci 226e1051a39Sopenharmony_ci tin[0] = tin0; 227e1051a39Sopenharmony_ci tin[1] = tin1; 228e1051a39Sopenharmony_ci DES_encrypt3((DES_LONG *)tin, ks1, ks2, ks3); 229e1051a39Sopenharmony_ci tout0 = tin[0]; 230e1051a39Sopenharmony_ci tout1 = tin[1]; 231e1051a39Sopenharmony_ci 232e1051a39Sopenharmony_ci l2c(tout0, out); 233e1051a39Sopenharmony_ci l2c(tout1, out); 234e1051a39Sopenharmony_ci } 235e1051a39Sopenharmony_ci if (l != -8) { 236e1051a39Sopenharmony_ci c2ln(in, tin0, tin1, l + 8); 237e1051a39Sopenharmony_ci tin0 ^= tout0; 238e1051a39Sopenharmony_ci tin1 ^= tout1; 239e1051a39Sopenharmony_ci 240e1051a39Sopenharmony_ci tin[0] = tin0; 241e1051a39Sopenharmony_ci tin[1] = tin1; 242e1051a39Sopenharmony_ci DES_encrypt3((DES_LONG *)tin, ks1, ks2, ks3); 243e1051a39Sopenharmony_ci tout0 = tin[0]; 244e1051a39Sopenharmony_ci tout1 = tin[1]; 245e1051a39Sopenharmony_ci 246e1051a39Sopenharmony_ci l2c(tout0, out); 247e1051a39Sopenharmony_ci l2c(tout1, out); 248e1051a39Sopenharmony_ci } 249e1051a39Sopenharmony_ci iv = &(*ivec)[0]; 250e1051a39Sopenharmony_ci l2c(tout0, iv); 251e1051a39Sopenharmony_ci l2c(tout1, iv); 252e1051a39Sopenharmony_ci } else { 253e1051a39Sopenharmony_ci register DES_LONG t0, t1; 254e1051a39Sopenharmony_ci 255e1051a39Sopenharmony_ci c2l(iv, xor0); 256e1051a39Sopenharmony_ci c2l(iv, xor1); 257e1051a39Sopenharmony_ci for (l -= 8; l >= 0; l -= 8) { 258e1051a39Sopenharmony_ci c2l(in, tin0); 259e1051a39Sopenharmony_ci c2l(in, tin1); 260e1051a39Sopenharmony_ci 261e1051a39Sopenharmony_ci t0 = tin0; 262e1051a39Sopenharmony_ci t1 = tin1; 263e1051a39Sopenharmony_ci 264e1051a39Sopenharmony_ci tin[0] = tin0; 265e1051a39Sopenharmony_ci tin[1] = tin1; 266e1051a39Sopenharmony_ci DES_decrypt3((DES_LONG *)tin, ks1, ks2, ks3); 267e1051a39Sopenharmony_ci tout0 = tin[0]; 268e1051a39Sopenharmony_ci tout1 = tin[1]; 269e1051a39Sopenharmony_ci 270e1051a39Sopenharmony_ci tout0 ^= xor0; 271e1051a39Sopenharmony_ci tout1 ^= xor1; 272e1051a39Sopenharmony_ci l2c(tout0, out); 273e1051a39Sopenharmony_ci l2c(tout1, out); 274e1051a39Sopenharmony_ci xor0 = t0; 275e1051a39Sopenharmony_ci xor1 = t1; 276e1051a39Sopenharmony_ci } 277e1051a39Sopenharmony_ci if (l != -8) { 278e1051a39Sopenharmony_ci c2l(in, tin0); 279e1051a39Sopenharmony_ci c2l(in, tin1); 280e1051a39Sopenharmony_ci 281e1051a39Sopenharmony_ci t0 = tin0; 282e1051a39Sopenharmony_ci t1 = tin1; 283e1051a39Sopenharmony_ci 284e1051a39Sopenharmony_ci tin[0] = tin0; 285e1051a39Sopenharmony_ci tin[1] = tin1; 286e1051a39Sopenharmony_ci DES_decrypt3((DES_LONG *)tin, ks1, ks2, ks3); 287e1051a39Sopenharmony_ci tout0 = tin[0]; 288e1051a39Sopenharmony_ci tout1 = tin[1]; 289e1051a39Sopenharmony_ci 290e1051a39Sopenharmony_ci tout0 ^= xor0; 291e1051a39Sopenharmony_ci tout1 ^= xor1; 292e1051a39Sopenharmony_ci l2cn(tout0, tout1, out, l + 8); 293e1051a39Sopenharmony_ci xor0 = t0; 294e1051a39Sopenharmony_ci xor1 = t1; 295e1051a39Sopenharmony_ci } 296e1051a39Sopenharmony_ci 297e1051a39Sopenharmony_ci iv = &(*ivec)[0]; 298e1051a39Sopenharmony_ci l2c(xor0, iv); 299e1051a39Sopenharmony_ci l2c(xor1, iv); 300e1051a39Sopenharmony_ci } 301e1051a39Sopenharmony_ci tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; 302e1051a39Sopenharmony_ci tin[0] = tin[1] = 0; 303e1051a39Sopenharmony_ci} 304e1051a39Sopenharmony_ci 305e1051a39Sopenharmony_ci#endif /* DES_DEFAULT_OPTIONS */ 306