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);
125 #include <openssl/evp.h>
128 DesEncrypt(const unsigned char *clear, const unsigned char *key, unsigned char *cipher)
131 unsigned int clen = 0;
132 unsigned char des_key[8];
134 PPP_CIPHER_CTX *ctx = PPP_CIPHER_CTX_new();
137 MakeKey(key, des_key);
139 if (PPP_CipherInit(ctx, PPP_des_ecb(), des_key, NULL, 1)) {
141 if (PPP_CipherUpdate(ctx, cipher, &clen, clear, 8)) {
143 if (PPP_CipherFinal(ctx, cipher + clen, &clen)) {
150 PPP_CIPHER_CTX_free(ctx);
157 DesDecrypt(const unsigned char *cipher, const unsigned char *key, unsigned char *clear)
160 unsigned int clen = 0;
161 unsigned char des_key[8];
163 PPP_CIPHER_CTX *ctx = PPP_CIPHER_CTX_new();
166 MakeKey(key, des_key);
168 if (PPP_CipherInit(ctx, PPP_des_ecb(), des_key, NULL, 0)) {
170 if (PPP_CipherUpdate(ctx, clear, &clen, cipher, 8)) {
172 if (PPP_CipherFinal(ctx, clear + clen, &clen)) {
179 PPP_CIPHER_CTX_free(ctx);
185 #ifdef UNIT_TEST_MSCRYPTO
191 * The test-vectors are taken from RFC2759.
195 unsigned char Challenge[8] = {
196 0xD0, 0x2E, 0x43, 0x86, 0xBC, 0xE9, 0x12, 0x26
199 unsigned char ZPasswordHash[24] = {
200 0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6,
201 0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE
204 unsigned char expected[24] = {
205 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E,
206 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54,
207 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF
209 unsigned char response[24] = {};
210 unsigned int retval = 0;
212 DesEncrypt(Challenge, ZPasswordHash + 0, response + 0);
213 DesEncrypt(Challenge, ZPasswordHash + 7, response + 8);
214 DesEncrypt(Challenge, ZPasswordHash + 14, response + 16);
216 return memcmp(response, expected, sizeof(response)) == 0;
221 unsigned char Challenge[8] = {
222 0xD0, 0x2E, 0x43, 0x86, 0xBC, 0xE9, 0x12, 0x26
225 unsigned char ZPasswordHash[24] = {
226 0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6,
227 0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE
230 unsigned char Response[24] = {
231 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E,
232 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54,
233 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF
235 unsigned char Output[8];
236 unsigned int failure = 0;
238 if (DesDecrypt(Response + 0, ZPasswordHash + 0, Output)) {
239 failure += memcmp(Challenge, Output, sizeof(Challenge));
242 if (DesDecrypt(Response + 8, ZPasswordHash + 7, Output)) {
243 failure += memcmp(Challenge, Output, sizeof(Challenge));
246 if (DesDecrypt(Response +16, ZPasswordHash +14, Output)) {
247 failure += memcmp(Challenge, Output, sizeof(Challenge));
253 int main(int argc, char *argv[])
257 if (!PPP_crypto_init()) {
258 printf("Couldn't initialize crypto test\n");
262 if (!test_encrypt()) {
263 printf("CHAP DES encryption test failed\n");
267 if (!test_decrypt()) {
268 printf("CHAP DES decryption test failed\n");
272 if (!PPP_crypto_deinit()) {
273 printf("Couldn't deinitialize crypto test\n");