]> git.ozlabs.org Git - ppp.git/blob - pppd/crypto.c
pppd man page: Update header to refer to pppd 2.5.x
[ppp.git] / pppd / crypto.c
1 /* ppp-crypto.c - Generic API for access to crypto/digest functions.
2  *
3  * Copyright (c) 2022 Eivind Næss. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. The name(s) of the authors of this software must not be used to
18  *    endorse or promote products derived from this software without
19  *    prior written permission.
20  *
21  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
22  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
23  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
24  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
25  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
26  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
27  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28  */
29
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include "crypto.h"
39 #include "crypto-priv.h"
40
41 #ifdef PPP_WITH_OPENSSL
42 #include <openssl/opensslv.h>
43 #endif
44
45 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
46 #include <openssl/provider.h>
47 struct crypto_ctx {
48
49     OSSL_PROVIDER *legacy;
50     OSSL_PROVIDER *provider;
51 } g_crypto_ctx;
52 #endif
53
54 PPP_MD_CTX *PPP_MD_CTX_new()
55 {
56     return (PPP_MD_CTX*) calloc(1, sizeof(PPP_MD_CTX));
57 }
58
59 void PPP_MD_CTX_free(PPP_MD_CTX* ctx)
60 {
61     if (ctx) {
62         if (ctx->md.clean_fn) {
63             ctx->md.clean_fn(ctx);
64         }
65         free(ctx);
66     }
67 }
68
69 int PPP_DigestInit(PPP_MD_CTX *ctx, const PPP_MD *type)
70 {
71     if (ctx) {
72         ctx->md = *type;
73         if (ctx->md.init_fn) {
74             return ctx->md.init_fn(ctx);
75         }
76     }
77     return 0;
78 }
79
80 int PPP_DigestUpdate(PPP_MD_CTX *ctx, const void *data, size_t length)
81 {
82     if (ctx && ctx->md.update_fn) {
83         return ctx->md.update_fn(ctx, data, length);
84     }
85     return 0;
86 }
87
88 int PPP_DigestFinal(PPP_MD_CTX *ctx, unsigned char *out, unsigned int *outlen)
89 {
90     if (ctx && ctx->md.final_fn) {
91         return ctx->md.final_fn(ctx, out, outlen);
92     }
93     return 0;
94 }
95
96 PPP_CIPHER_CTX *PPP_CIPHER_CTX_new(void)
97 {
98     return calloc(1, sizeof(PPP_CIPHER_CTX));
99 }
100
101 void PPP_CIPHER_CTX_free(PPP_CIPHER_CTX *ctx)
102 {
103     if (ctx) {
104         if (ctx->cipher.clean_fn) {
105             ctx->cipher.clean_fn(ctx);
106         }
107         memset(ctx->iv, 0, sizeof(ctx->iv));
108         memset(ctx->key, 0, sizeof(ctx->key));
109         free(ctx);
110     }
111 }
112
113 int PPP_CipherInit(PPP_CIPHER_CTX *ctx, const PPP_CIPHER *cipher, const unsigned char *key, const unsigned char *iv, int encr)
114 {
115     if (ctx && cipher) {
116         ctx->is_encr = encr;
117         ctx->cipher = *cipher;
118         if (ctx->cipher.init_fn) {
119             ctx->cipher.init_fn(ctx, key, iv);
120         }
121         return 1;
122     }
123     return 0;
124 }
125
126 int PPP_CipherUpdate(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl)
127 {
128     if (ctx && ctx->cipher.update_fn) {
129         return ctx->cipher.update_fn(ctx, out, outl, in, inl);
130     }
131     return 0;
132 }
133
134 int PPP_CipherFinal(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
135 {
136     if (ctx && ctx->cipher.final_fn) {
137         return ctx->cipher.final_fn(ctx, out, outl);
138     }
139     return 0;
140 }
141
142 int PPP_crypto_init()
143 {
144     int retval = 0;
145
146 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
147     g_crypto_ctx.legacy = OSSL_PROVIDER_load(NULL, "legacy");
148     if (g_crypto_ctx.legacy == NULL)
149     {
150         goto done;
151     }
152
153     g_crypto_ctx.provider = OSSL_PROVIDER_load(NULL, "default");
154     if (g_crypto_ctx.provider == NULL)
155     {
156         goto done;
157     }
158 #endif
159     retval = 1;
160
161 done:
162
163     return retval;
164 }
165
166 int PPP_crypto_deinit()
167 {
168 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
169     if (g_crypto_ctx.legacy) {
170         OSSL_PROVIDER_unload(g_crypto_ctx.legacy);
171         g_crypto_ctx.legacy = NULL;
172     }
173
174     if (g_crypto_ctx.provider) {
175         OSSL_PROVIDER_unload(g_crypto_ctx.provider);
176         g_crypto_ctx.provider = NULL;
177     }
178 #endif
179     return 1;
180 }
181
182 #ifdef UNIT_TEST
183 #include <stdio.h>
184
185 int test_md4()
186 {
187     PPP_MD_CTX* ctx = NULL;
188     int success = 0;
189
190     unsigned char data[84] = {
191         0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
192         0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69,
193         0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73,
194         0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
195         0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
196         0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
197         0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
198         0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74,
199         0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
200         0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
201         0x6b, 0x65, 0x79, 0x2e
202     };
203
204     unsigned int  hash_len;
205     unsigned char hash[MD4_DIGEST_LENGTH];
206     unsigned char result[MD4_DIGEST_LENGTH] = {
207         0x58, 0xcb, 0x37, 0x91, 0x1d, 0x06, 0x7b, 0xdf,
208         0xfd, 0x48, 0x6d, 0x87, 0x4a, 0x35, 0x5b, 0xd4
209     };
210
211     ctx = PPP_MD_CTX_new();
212     if (ctx) {
213
214         if (PPP_DigestInit(ctx, PPP_md4())) {
215
216             if (PPP_DigestUpdate(ctx, &data, sizeof(data))) {
217
218                 hash_len = sizeof(hash);
219                 if (PPP_DigestFinal(ctx, hash, &hash_len)) {
220
221                     if (memcmp(hash, result, MD4_DIGEST_LENGTH) == 0) {
222                         success = 1;
223                     }
224                 }
225             }
226         }
227         PPP_MD_CTX_free(ctx);
228     }
229
230     return success;
231 }
232
233 int test_md5()
234 {
235     PPP_MD_CTX* ctx = NULL;
236     int success = 0;
237
238     unsigned char data[84] = {
239         0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
240         0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69,
241         0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73,
242         0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
243         0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
244         0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
245         0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
246         0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74,
247         0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
248         0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
249         0x6b, 0x65, 0x79, 0x2e
250     };
251
252     unsigned int  hash_len;
253     unsigned char hash[MD5_DIGEST_LENGTH];
254     unsigned char result[MD5_DIGEST_LENGTH] = {
255         0x8b, 0xe3, 0x5e, 0x2c, 0x9f, 0x95, 0xbf, 0x4e,
256         0x16, 0xe4, 0x53, 0xbe, 0x52, 0xf4, 0xbc, 0x4e
257     };
258
259     ctx = PPP_MD_CTX_new();
260     if (ctx) {
261
262         if (PPP_DigestInit(ctx, PPP_md5())) {
263
264             if (PPP_DigestUpdate(ctx, &data, sizeof(data))) {
265
266                 hash_len = sizeof(hash);
267                 if (PPP_DigestFinal(ctx, hash, &hash_len)) {
268
269                     if (memcmp(hash, result, MD5_DIGEST_LENGTH) == 0) {
270                         success = 1;
271                     }
272                 }
273             }
274         }
275         PPP_MD_CTX_free(ctx);
276     }
277
278     return success;
279 }
280
281 int test_sha()
282 {
283     PPP_MD_CTX* ctx = NULL;
284     int success = 0;
285
286     unsigned char data[84] = {
287         0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
288         0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69,
289         0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73,
290         0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
291         0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
292         0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
293         0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
294         0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74,
295         0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
296         0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
297         0x6b, 0x65, 0x79, 0x2e
298     };
299
300     unsigned int  hash_len;
301     unsigned char hash[SHA_DIGEST_LENGTH];
302     unsigned char result[SHA_DIGEST_LENGTH] = {
303         0xa8, 0x03, 0xae, 0x21, 0x30, 0xd8, 0x40, 0xbe,
304         0x27, 0xa3, 0x47, 0xc7, 0x7a, 0x90, 0xe6, 0xa3,
305         0x5b, 0xd5, 0x0e, 0x45
306     };
307
308     ctx = PPP_MD_CTX_new();
309     if (ctx) {
310
311         if (PPP_DigestInit(ctx, PPP_sha1())) {
312
313             if (PPP_DigestUpdate(ctx, &data, sizeof(data))) {
314
315                 hash_len = sizeof(hash);
316                 if (PPP_DigestFinal(ctx, hash, &hash_len)) {
317
318                     if (memcmp(hash, result, SHA_DIGEST_LENGTH) == 0) {
319                         success = 1;
320                     }
321                 }
322             }
323         }
324         PPP_MD_CTX_free(ctx);
325     }
326
327     return success;
328 }
329
330 int test_des_encrypt()
331 {
332     PPP_CIPHER_CTX* ctx = NULL;
333     int success = 0;
334
335     unsigned char key[8] = {
336         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
337     };
338
339     unsigned char plain[80] = {
340         0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
341         0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69,
342         0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73,
343         0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
344         0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
345         0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
346         0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
347         0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74,
348         0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
349         0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20
350     };
351     unsigned char expect[80] = {
352         0x45, 0xdb, 0x80, 0x45, 0x16, 0xd0, 0x6d, 0x60,
353         0x92, 0x23, 0x4b, 0xd3, 0x9d, 0x36, 0xb8, 0x1a,
354         0xa4, 0x1a, 0xf7, 0xb1, 0x60, 0xfb, 0x74, 0x16,
355         0xa6, 0xdc, 0xe1, 0x14, 0xb7, 0xed, 0x48, 0x5a,
356         0x2b, 0xed, 0x68, 0x9d, 0x19, 0xd6, 0xb1, 0xb8,
357         0x91, 0xff, 0xea, 0x62, 0xac, 0xe7, 0x49, 0xdd,
358         0xfa, 0x4d, 0xa4, 0x01, 0x3f, 0xea, 0xca, 0xb4,
359         0xb6, 0xdc, 0xd3, 0x04, 0x45, 0x07, 0x74, 0xed,
360         0xa6, 0xdc, 0xe1, 0x14, 0xb7, 0xed, 0x48, 0x5a,
361         0xbb, 0x9b, 0x13, 0x31, 0xf4, 0xa9, 0x32, 0x49
362     };
363
364     unsigned char cipher[80] = {};
365     int cipher_len = 0;
366     int offset = 0;
367
368
369     ctx = PPP_CIPHER_CTX_new();
370     if (ctx) {
371
372         if (PPP_CipherInit(ctx, PPP_des_ecb(), key, NULL, 1)) {
373
374             if (PPP_CipherUpdate(ctx, cipher, &cipher_len, plain, sizeof(plain))) {
375
376                 offset += cipher_len;
377
378                 if (PPP_CipherFinal(ctx, cipher+offset, &cipher_len)) {
379
380                     if (memcmp(cipher, expect, 80) == 0) {
381
382                         success = 1;
383                     }
384                 }
385             }
386         }
387         PPP_CIPHER_CTX_free(ctx);
388     }
389
390     return success;
391 }
392
393
394 int test_des_decrypt()
395 {
396     PPP_CIPHER_CTX* ctx = NULL;
397     int success = 0;
398
399     unsigned char key[8] = {
400         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
401     };
402
403     unsigned char cipher[80] = {
404         0x45, 0xdb, 0x80, 0x45, 0x16, 0xd0, 0x6d, 0x60,
405         0x92, 0x23, 0x4b, 0xd3, 0x9d, 0x36, 0xb8, 0x1a,
406         0xa4, 0x1a, 0xf7, 0xb1, 0x60, 0xfb, 0x74, 0x16,
407         0xa6, 0xdc, 0xe1, 0x14, 0xb7, 0xed, 0x48, 0x5a,
408         0x2b, 0xed, 0x68, 0x9d, 0x19, 0xd6, 0xb1, 0xb8,
409         0x91, 0xff, 0xea, 0x62, 0xac, 0xe7, 0x49, 0xdd,
410         0xfa, 0x4d, 0xa4, 0x01, 0x3f, 0xea, 0xca, 0xb4,
411         0xb6, 0xdc, 0xd3, 0x04, 0x45, 0x07, 0x74, 0xed,
412         0xa6, 0xdc, 0xe1, 0x14, 0xb7, 0xed, 0x48, 0x5a,
413         0xbb, 0x9b, 0x13, 0x31, 0xf4, 0xa9, 0x32, 0x49
414     };
415
416     unsigned char expect[80] = {
417         0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
418         0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69,
419         0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73,
420         0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
421         0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
422         0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
423         0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
424         0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74,
425         0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
426         0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20
427     };
428
429     unsigned char plain[80] = {};
430     int outlen = 0;
431     int offset = 0;
432
433     ctx = PPP_CIPHER_CTX_new();
434     if (ctx) {
435
436         if (PPP_CipherInit(ctx, PPP_des_ecb(), key, NULL, 0)) {
437
438             if (PPP_CipherUpdate(ctx, plain, &outlen, cipher, sizeof(cipher))) {
439
440                 offset += outlen;
441
442                 if (PPP_CipherFinal(ctx, plain+offset, &outlen)) {
443
444                     if (memcmp(plain, expect, 80) == 0) {
445
446                         success = 1;
447                     }
448                 }
449             }
450         }
451         PPP_CIPHER_CTX_free(ctx);
452     }
453
454     return success;
455 }
456
457 int main(int argc, char *argv[])
458 {
459     int failure = 0;
460
461     if (!PPP_crypto_init()) {
462         printf("Couldn't initialize crypto test\n");
463         return -1;
464     }
465
466     if (!test_md4()) {
467         printf("MD4 test failed\n");
468         failure++;
469     }
470
471     if (!test_md5()) {
472         printf("MD5 test failed\n");
473         failure++;
474     }
475
476     if (!test_sha()) {
477         printf("SHA test failed\n");
478         failure++;
479     }
480
481     if (!test_des_encrypt()) {
482         printf("DES encryption test failed\n");
483         failure++;
484     }
485
486     if (!test_des_decrypt()) {
487         printf("DES decryption test failed\n");
488         failure++;
489     }
490
491     if (!PPP_crypto_deinit()) {
492         printf("Couldn't deinitialize crypto test\n");
493         return -1;
494     }
495
496     return failure;
497 }
498
499 #endif