2 * pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1
4 * Extracted from chap_ms.c by James Carlson.
6 * Copyright (c) 1995 Eric Rosenquist. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
20 * 3. The name(s) of the authors of this software must not be used to
21 * endorse or promote products derived from this software without
22 * prior written permission.
24 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
25 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
26 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
27 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
28 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
29 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
30 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 * Sections of this code holds different copyright information.
42 #include "crypto_ms.h"
46 * DES_set_odd_parity function are imported from openssl 3.0 project with the
49 * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
51 * Licensed under the Apache License 2.0 (the "License"). You may not use
52 * this file except in compliance with the License. You can obtain a copy
53 * in the file LICENSE in the source distribution or at
54 * https://www.openssl.org/source/license.html
56 typedef unsigned char DES_cblock[8];
57 #define DES_KEY_SZ (sizeof(DES_cblock))
59 static const unsigned char odd_parity[256] = {
60 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,
61 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
62 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
63 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
64 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
65 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
66 97, 97, 98, 98, 100, 100, 103, 103, 104, 104, 107, 107, 109, 109, 110,
68 112, 112, 115, 115, 117, 117, 118, 118, 121, 121, 122, 122, 124, 124, 127,
70 128, 128, 131, 131, 133, 133, 134, 134, 137, 137, 138, 138, 140, 140, 143,
72 145, 145, 146, 146, 148, 148, 151, 151, 152, 152, 155, 155, 157, 157, 158,
74 161, 161, 162, 162, 164, 164, 167, 167, 168, 168, 171, 171, 173, 173, 174,
76 176, 176, 179, 179, 181, 181, 182, 182, 185, 185, 186, 186, 188, 188, 191,
78 193, 193, 194, 194, 196, 196, 199, 199, 200, 200, 203, 203, 205, 205, 206,
80 208, 208, 211, 211, 213, 213, 214, 214, 217, 217, 218, 218, 220, 220, 223,
82 224, 224, 227, 227, 229, 229, 230, 230, 233, 233, 234, 234, 236, 236, 239,
84 241, 241, 242, 242, 244, 244, 247, 247, 248, 248, 251, 251, 253, 253, 254,
88 static void DES_set_odd_parity(DES_cblock *key)
91 for (i = 0; i < DES_KEY_SZ; i++)
92 (*key)[i] = odd_parity[(*key)[i]];
96 Get7Bits(const unsigned char *input, int startBit)
100 word = (unsigned)input[startBit / 8] << 8;
101 word |= (unsigned)input[startBit / 8 + 1];
103 word >>= 15 - (startBit % 8 + 7);
109 MakeKey(const unsigned char *key, unsigned char *des_key)
111 /* key IN 56 bit DES key missing parity bits */
112 /* des_key OUT 64 bit DES key with parity bits added */
113 des_key[0] = Get7Bits(key, 0);
114 des_key[1] = Get7Bits(key, 7);
115 des_key[2] = Get7Bits(key, 14);
116 des_key[3] = Get7Bits(key, 21);
117 des_key[4] = Get7Bits(key, 28);
118 des_key[5] = Get7Bits(key, 35);
119 des_key[6] = Get7Bits(key, 42);
120 des_key[7] = Get7Bits(key, 49);
122 DES_set_odd_parity((DES_cblock *)des_key);
126 DesEncrypt(const unsigned char *clear, const unsigned char *key, unsigned char *cipher)
129 unsigned int clen = 0;
130 unsigned char des_key[8];
132 PPP_CIPHER_CTX *ctx = PPP_CIPHER_CTX_new();
135 MakeKey(key, des_key);
137 if (PPP_CipherInit(ctx, PPP_des_ecb(), des_key, NULL, 1)) {
139 if (PPP_CipherUpdate(ctx, cipher, &clen, clear, 8)) {
141 if (PPP_CipherFinal(ctx, cipher + clen, &clen)) {
148 PPP_CIPHER_CTX_free(ctx);
155 DesDecrypt(const unsigned char *cipher, const unsigned char *key, unsigned char *clear)
158 unsigned int clen = 0;
159 unsigned char des_key[8];
161 PPP_CIPHER_CTX *ctx = PPP_CIPHER_CTX_new();
164 MakeKey(key, des_key);
166 if (PPP_CipherInit(ctx, PPP_des_ecb(), des_key, NULL, 0)) {
168 if (PPP_CipherUpdate(ctx, clear, &clen, cipher, 8)) {
170 if (PPP_CipherFinal(ctx, clear + clen, &clen)) {
177 PPP_CIPHER_CTX_free(ctx);
183 #ifdef UNIT_TEST_MSCRYPTO
189 * The test-vectors are taken from RFC2759.
193 unsigned char Challenge[8] = {
194 0xD0, 0x2E, 0x43, 0x86, 0xBC, 0xE9, 0x12, 0x26
197 unsigned char ZPasswordHash[24] = {
198 0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6,
199 0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE
202 unsigned char expected[24] = {
203 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E,
204 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54,
205 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF
207 unsigned char response[24] = {};
208 unsigned int retval = 0;
210 DesEncrypt(Challenge, ZPasswordHash + 0, response + 0);
211 DesEncrypt(Challenge, ZPasswordHash + 7, response + 8);
212 DesEncrypt(Challenge, ZPasswordHash + 14, response + 16);
214 return memcmp(response, expected, sizeof(response)) == 0;
219 unsigned char Challenge[8] = {
220 0xD0, 0x2E, 0x43, 0x86, 0xBC, 0xE9, 0x12, 0x26
223 unsigned char ZPasswordHash[24] = {
224 0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6,
225 0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE
228 unsigned char Response[24] = {
229 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E,
230 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54,
231 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF
233 unsigned char Output[8];
234 unsigned int failure = 0;
236 if (DesDecrypt(Response + 0, ZPasswordHash + 0, Output)) {
237 failure += memcmp(Challenge, Output, sizeof(Challenge));
240 if (DesDecrypt(Response + 8, ZPasswordHash + 7, Output)) {
241 failure += memcmp(Challenge, Output, sizeof(Challenge));
244 if (DesDecrypt(Response +16, ZPasswordHash +14, Output)) {
245 failure += memcmp(Challenge, Output, sizeof(Challenge));
251 int main(int argc, char *argv[])
255 if (!PPP_crypto_init()) {
256 printf("Couldn't initialize crypto test\n");
260 if (!test_encrypt()) {
261 printf("CHAP DES encryption test failed\n");
265 if (!test_decrypt()) {
266 printf("CHAP DES decryption test failed\n");
270 if (!PPP_crypto_deinit()) {
271 printf("Couldn't deinitialize crypto test\n");