1/* rfc2268.c - The cipher described in rfc2268; aka Ron's Cipher 2. 2 * Copyright (C) 2003 Nikos Mavroyanopoulos 3 * Copyright (C) 2004 Free Software Foundation, Inc. 4 * 5 * This file is part of Libgcrypt 6 * 7 * Libgcrypt is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU Lesser general Public License as 9 * published by the Free Software Foundation; either version 2.1 of 10 * the License, or (at your option) any later version. 11 * 12 * Libgcrypt is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 20 */ 21 22/* This implementation was written by Nikos Mavroyanopoulos for GNUTLS 23 * as a Libgcrypt module (gnutls/lib/x509/rc2.c) and later adapted for 24 * direct use by Libgcrypt by Werner Koch. This implementation is 25 * only useful for pkcs#12 decryption. 26 * 27 * The implementation here is based on Peter Gutmann's RRC.2 paper. 28 */ 29 30 31#include <config.h> 32#include <stdio.h> 33#include <stdlib.h> 34#include <string.h> 35#include "g10lib.h" 36#include "types.h" 37#include "cipher.h" 38 39#define RFC2268_BLOCKSIZE 8 40 41typedef struct 42{ 43 u16 S[64]; 44} RFC2268_context; 45 46static const unsigned char rfc2268_sbox[] = { 47 217, 120, 249, 196, 25, 221, 181, 237, 48 40, 233, 253, 121, 74, 160, 216, 157, 49 198, 126, 55, 131, 43, 118, 83, 142, 50 98, 76, 100, 136, 68, 139, 251, 162, 51 23, 154, 89, 245, 135, 179, 79, 19, 52 97, 69, 109, 141, 9, 129, 125, 50, 53 189, 143, 64, 235, 134, 183, 123, 11, 54 240, 149, 33, 34, 92, 107, 78, 130, 55 84, 214, 101, 147, 206, 96, 178, 28, 56 115, 86, 192, 20, 167, 140, 241, 220, 57 18, 117, 202, 31, 59, 190, 228, 209, 58 66, 61, 212, 48, 163, 60, 182, 38, 59 111, 191, 14, 218, 70, 105, 7, 87, 60 39, 242, 29, 155, 188, 148, 67, 3, 61 248, 17, 199, 246, 144, 239, 62, 231, 62 6, 195, 213, 47, 200, 102, 30, 215, 63 8, 232, 234, 222, 128, 82, 238, 247, 64 132, 170, 114, 172, 53, 77, 106, 42, 65 150, 26, 210, 113, 90, 21, 73, 116, 66 75, 159, 208, 94, 4, 24, 164, 236, 67 194, 224, 65, 110, 15, 81, 203, 204, 68 36, 145, 175, 80, 161, 244, 112, 57, 69 153, 124, 58, 133, 35, 184, 180, 122, 70 252, 2, 54, 91, 37, 85, 151, 49, 71 45, 93, 250, 152, 227, 138, 146, 174, 72 5, 223, 41, 16, 103, 108, 186, 201, 73 211, 0, 230, 207, 225, 158, 168, 44, 74 99, 22, 1, 63, 88, 226, 137, 169, 75 13, 56, 52, 27, 171, 51, 255, 176, 76 187, 72, 12, 95, 185, 177, 205, 46, 77 197, 243, 219, 71, 229, 165, 156, 119, 78 10, 166, 32, 104, 254, 127, 193, 173 79}; 80 81#define rotl16(x,n) (((x) << ((u16)(n))) | ((x) >> (16 - (u16)(n)))) 82#define rotr16(x,n) (((x) >> ((u16)(n))) | ((x) << (16 - (u16)(n)))) 83 84static const char *selftest (void); 85 86 87static void 88do_encrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf) 89{ 90 RFC2268_context *ctx = context; 91 register int i, j; 92 u16 word0 = 0, word1 = 0, word2 = 0, word3 = 0; 93 94 word0 = (word0 << 8) | inbuf[1]; 95 word0 = (word0 << 8) | inbuf[0]; 96 word1 = (word1 << 8) | inbuf[3]; 97 word1 = (word1 << 8) | inbuf[2]; 98 word2 = (word2 << 8) | inbuf[5]; 99 word2 = (word2 << 8) | inbuf[4]; 100 word3 = (word3 << 8) | inbuf[7]; 101 word3 = (word3 << 8) | inbuf[6]; 102 103 for (i = 0; i < 16; i++) 104 { 105 j = i * 4; 106 /* For some reason I cannot combine those steps. */ 107 word0 += (word1 & ~word3) + (word2 & word3) + ctx->S[j]; 108 word0 = rotl16(word0, 1); 109 110 word1 += (word2 & ~word0) + (word3 & word0) + ctx->S[j + 1]; 111 word1 = rotl16(word1, 2); 112 113 word2 += (word3 & ~word1) + (word0 & word1) + ctx->S[j + 2]; 114 word2 = rotl16(word2, 3); 115 116 word3 += (word0 & ~word2) + (word1 & word2) + ctx->S[j + 3]; 117 word3 = rotl16(word3, 5); 118 119 if (i == 4 || i == 10) 120 { 121 word0 += ctx->S[word3 & 63]; 122 word1 += ctx->S[word0 & 63]; 123 word2 += ctx->S[word1 & 63]; 124 word3 += ctx->S[word2 & 63]; 125 } 126 127 } 128 129 outbuf[0] = word0 & 255; 130 outbuf[1] = word0 >> 8; 131 outbuf[2] = word1 & 255; 132 outbuf[3] = word1 >> 8; 133 outbuf[4] = word2 & 255; 134 outbuf[5] = word2 >> 8; 135 outbuf[6] = word3 & 255; 136 outbuf[7] = word3 >> 8; 137} 138 139static void 140do_decrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf) 141{ 142 RFC2268_context *ctx = context; 143 register int i, j; 144 u16 word0 = 0, word1 = 0, word2 = 0, word3 = 0; 145 146 word0 = (word0 << 8) | inbuf[1]; 147 word0 = (word0 << 8) | inbuf[0]; 148 word1 = (word1 << 8) | inbuf[3]; 149 word1 = (word1 << 8) | inbuf[2]; 150 word2 = (word2 << 8) | inbuf[5]; 151 word2 = (word2 << 8) | inbuf[4]; 152 word3 = (word3 << 8) | inbuf[7]; 153 word3 = (word3 << 8) | inbuf[6]; 154 155 for (i = 15; i >= 0; i--) 156 { 157 j = i * 4; 158 159 word3 = rotr16(word3, 5); 160 word3 -= (word0 & ~word2) + (word1 & word2) + ctx->S[j + 3]; 161 162 word2 = rotr16(word2, 3); 163 word2 -= (word3 & ~word1) + (word0 & word1) + ctx->S[j + 2]; 164 165 word1 = rotr16(word1, 2); 166 word1 -= (word2 & ~word0) + (word3 & word0) + ctx->S[j + 1]; 167 168 word0 = rotr16(word0, 1); 169 word0 -= (word1 & ~word3) + (word2 & word3) + ctx->S[j]; 170 171 if (i == 5 || i == 11) 172 { 173 word3 = word3 - ctx->S[word2 & 63]; 174 word2 = word2 - ctx->S[word1 & 63]; 175 word1 = word1 - ctx->S[word0 & 63]; 176 word0 = word0 - ctx->S[word3 & 63]; 177 } 178 179 } 180 181 outbuf[0] = word0 & 255; 182 outbuf[1] = word0 >> 8; 183 outbuf[2] = word1 & 255; 184 outbuf[3] = word1 >> 8; 185 outbuf[4] = word2 & 255; 186 outbuf[5] = word2 >> 8; 187 outbuf[6] = word3 & 255; 188 outbuf[7] = word3 >> 8; 189} 190 191 192static gpg_err_code_t 193setkey_core (void *context, const unsigned char *key, unsigned int keylen, int with_phase2) 194{ 195 static int initialized; 196 static const char *selftest_failed; 197 RFC2268_context *ctx = context; 198 unsigned int i; 199 unsigned char *S, x; 200 int len; 201 int bits = keylen * 8; 202 203 if (!initialized) 204 { 205 initialized = 1; 206 selftest_failed = selftest (); 207 if (selftest_failed) 208 log_error ("RFC2268 selftest failed (%s).\n", selftest_failed); 209 } 210 if (selftest_failed) 211 return GPG_ERR_SELFTEST_FAILED; 212 213 if (keylen < 40 / 8) /* We want at least 40 bits. */ 214 return GPG_ERR_INV_KEYLEN; 215 216 S = (unsigned char *) ctx->S; 217 218 for (i = 0; i < keylen; i++) 219 S[i] = key[i]; 220 221 for (i = keylen; i < 128; i++) 222 S[i] = rfc2268_sbox[(S[i - keylen] + S[i - 1]) & 255]; 223 224 S[0] = rfc2268_sbox[S[0]]; 225 226 /* Phase 2 - reduce effective key size to "bits". This was not 227 * discussed in Gutmann's paper. I've copied that from the public 228 * domain code posted in sci.crypt. */ 229 if (with_phase2) 230 { 231 len = (bits + 7) >> 3; 232 i = 128 - len; 233 x = rfc2268_sbox[S[i] & (255 >> (7 & -bits))]; 234 S[i] = x; 235 236 while (i--) 237 { 238 x = rfc2268_sbox[x ^ S[i + len]]; 239 S[i] = x; 240 } 241 } 242 243 /* Make the expanded key, endian independent. */ 244 for (i = 0; i < 64; i++) 245 ctx->S[i] = ( (u16) S[i * 2] | (((u16) S[i * 2 + 1]) << 8)); 246 247 return 0; 248} 249 250static gpg_err_code_t 251do_setkey (void *context, const unsigned char *key, unsigned int keylen) 252{ 253 return setkey_core (context, key, keylen, 1); 254} 255 256static const char * 257selftest (void) 258{ 259 RFC2268_context ctx; 260 unsigned char scratch[16]; 261 262 /* Test vectors from Peter Gutmann's paper. */ 263 static unsigned char key_1[] = 264 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 266 }; 267 static unsigned char plaintext_1[] = 268 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 269 static const unsigned char ciphertext_1[] = 270 { 0x1C, 0x19, 0x8A, 0x83, 0x8D, 0xF0, 0x28, 0xB7 }; 271 272 static unsigned char key_2[] = 273 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 274 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F 275 }; 276 static unsigned char plaintext_2[] = 277 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 278 static unsigned char ciphertext_2[] = 279 { 0x50, 0xDC, 0x01, 0x62, 0xBD, 0x75, 0x7F, 0x31 }; 280 281 /* This one was checked against libmcrypt's RFC2268. */ 282 static unsigned char key_3[] = 283 { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 285 }; 286 static unsigned char plaintext_3[] = 287 { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 288 static unsigned char ciphertext_3[] = 289 { 0x8f, 0xd1, 0x03, 0x89, 0x33, 0x6b, 0xf9, 0x5e }; 290 291 292 /* First test. */ 293 setkey_core (&ctx, key_1, sizeof(key_1), 0); 294 do_encrypt (&ctx, scratch, plaintext_1); 295 296 if (memcmp (scratch, ciphertext_1, sizeof(ciphertext_1))) 297 return "RFC2268 encryption test 1 failed."; 298 299 setkey_core (&ctx, key_1, sizeof(key_1), 0); 300 do_decrypt (&ctx, scratch, scratch); 301 if (memcmp (scratch, plaintext_1, sizeof(plaintext_1))) 302 return "RFC2268 decryption test 1 failed."; 303 304 /* Second test. */ 305 setkey_core (&ctx, key_2, sizeof(key_2), 0); 306 do_encrypt (&ctx, scratch, plaintext_2); 307 if (memcmp (scratch, ciphertext_2, sizeof(ciphertext_2))) 308 return "RFC2268 encryption test 2 failed."; 309 310 setkey_core (&ctx, key_2, sizeof(key_2), 0); 311 do_decrypt (&ctx, scratch, scratch); 312 if (memcmp (scratch, plaintext_2, sizeof(plaintext_2))) 313 return "RFC2268 decryption test 2 failed."; 314 315 /* Third test. */ 316 setkey_core(&ctx, key_3, sizeof(key_3), 0); 317 do_encrypt(&ctx, scratch, plaintext_3); 318 319 if (memcmp(scratch, ciphertext_3, sizeof(ciphertext_3))) 320 return "RFC2268 encryption test 3 failed."; 321 322 setkey_core (&ctx, key_3, sizeof(key_3), 0); 323 do_decrypt (&ctx, scratch, scratch); 324 if (memcmp(scratch, plaintext_3, sizeof(plaintext_3))) 325 return "RFC2268 decryption test 3 failed."; 326 327 return NULL; 328} 329 330 331 332static gcry_cipher_oid_spec_t oids_rfc2268_40[] = 333 { 334 /*{ "1.2.840.113549.3.2", GCRY_CIPHER_MODE_CBC },*/ 335 /* pbeWithSHAAnd40BitRC2_CBC */ 336 { "1.2.840.113549.1.12.1.6", GCRY_CIPHER_MODE_CBC }, 337 { NULL } 338 }; 339 340gcry_cipher_spec_t _gcry_cipher_spec_rfc2268_40 = { 341 "RFC2268_40", NULL, oids_rfc2268_40, 342 RFC2268_BLOCKSIZE, 40, sizeof(RFC2268_context), 343 do_setkey, do_encrypt, do_decrypt 344}; 345