1 /* ppp-crypto.c - Generic API for access to crypto/digest functions.
3 * Copyright (c) 2022 Eivind Næss. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
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
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.
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.
38 #include "ppp-crypto.h"
39 #include "ppp-crypto-priv.h"
41 #ifdef PPP_WITH_OPENSSL
42 #include <openssl/opensslv.h>
45 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
46 #include <openssl/provider.h>
49 OSSL_PROVIDER *legacy;
50 OSSL_PROVIDER *provider;
54 PPP_MD_CTX *PPP_MD_CTX_new()
56 return (PPP_MD_CTX*) calloc(1, sizeof(PPP_MD_CTX));
59 void PPP_MD_CTX_free(PPP_MD_CTX* ctx)
62 if (ctx->md.clean_fn) {
63 ctx->md.clean_fn(ctx);
69 int PPP_DigestInit(PPP_MD_CTX *ctx, const PPP_MD *type)
73 if (ctx->md.init_fn) {
74 return ctx->md.init_fn(ctx);
80 int PPP_DigestUpdate(PPP_MD_CTX *ctx, const void *data, size_t length)
82 if (ctx && ctx->md.update_fn) {
83 return ctx->md.update_fn(ctx, data, length);
88 int PPP_DigestFinal(PPP_MD_CTX *ctx, unsigned char *out, unsigned int *outlen)
90 if (ctx && ctx->md.final_fn) {
91 return ctx->md.final_fn(ctx, out, outlen);
96 PPP_CIPHER_CTX *PPP_CIPHER_CTX_new(void)
98 return calloc(1, sizeof(PPP_CIPHER_CTX));
101 void PPP_CIPHER_CTX_free(PPP_CIPHER_CTX *ctx)
104 if (ctx->cipher.clean_fn) {
105 ctx->cipher.clean_fn(ctx);
107 memset(ctx->iv, 0, sizeof(ctx->iv));
108 memset(ctx->key, 0, sizeof(ctx->key));
113 int PPP_CipherInit(PPP_CIPHER_CTX *ctx, const PPP_CIPHER *cipher, const unsigned char *key, const unsigned char *iv, int encr)
117 ctx->cipher = *cipher;
118 if (ctx->cipher.init_fn) {
119 ctx->cipher.init_fn(ctx, key, iv);
126 int PPP_CipherUpdate(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl)
128 if (ctx && ctx->cipher.update_fn) {
129 return ctx->cipher.update_fn(ctx, out, outl, in, inl);
134 int PPP_CipherFinal(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
136 if (ctx && ctx->cipher.final_fn) {
137 return ctx->cipher.final_fn(ctx, out, outl);
142 int PPP_crypto_init()
146 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
147 g_crypto_ctx.legacy = OSSL_PROVIDER_load(NULL, "legacy");
148 if (g_crypto_ctx.legacy == NULL)
153 g_crypto_ctx.provider = OSSL_PROVIDER_load(NULL, "default");
154 if (g_crypto_ctx.provider == NULL)
166 int PPP_crypto_deinit()
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;
174 if (g_crypto_ctx.provider) {
175 OSSL_PROVIDER_unload(g_crypto_ctx.provider);
176 g_crypto_ctx.provider = NULL;
187 PPP_MD_CTX* ctx = NULL;
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
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
211 ctx = PPP_MD_CTX_new();
214 if (PPP_DigestInit(ctx, PPP_md4())) {
216 if (PPP_DigestUpdate(ctx, &data, sizeof(data))) {
218 hash_len = sizeof(hash);
219 if (PPP_DigestFinal(ctx, hash, &hash_len)) {
221 if (memcmp(hash, result, MD4_DIGEST_LENGTH) == 0) {
227 PPP_MD_CTX_free(ctx);
235 PPP_MD_CTX* ctx = NULL;
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
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
259 ctx = PPP_MD_CTX_new();
262 if (PPP_DigestInit(ctx, PPP_md5())) {
264 if (PPP_DigestUpdate(ctx, &data, sizeof(data))) {
266 hash_len = sizeof(hash);
267 if (PPP_DigestFinal(ctx, hash, &hash_len)) {
269 if (memcmp(hash, result, MD5_DIGEST_LENGTH) == 0) {
275 PPP_MD_CTX_free(ctx);
283 PPP_MD_CTX* ctx = NULL;
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
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
308 ctx = PPP_MD_CTX_new();
311 if (PPP_DigestInit(ctx, PPP_sha1())) {
313 if (PPP_DigestUpdate(ctx, &data, sizeof(data))) {
315 hash_len = sizeof(hash);
316 if (PPP_DigestFinal(ctx, hash, &hash_len)) {
318 if (memcmp(hash, result, SHA_DIGEST_LENGTH) == 0) {
324 PPP_MD_CTX_free(ctx);
330 int test_des_encrypt()
332 PPP_CIPHER_CTX* ctx = NULL;
335 unsigned char key[8] = {
336 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
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
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
364 unsigned char cipher[80] = {};
369 ctx = PPP_CIPHER_CTX_new();
372 if (PPP_CipherInit(ctx, PPP_des_ecb(), key, NULL, 1)) {
374 if (PPP_CipherUpdate(ctx, cipher, &cipher_len, plain, sizeof(plain))) {
376 offset += cipher_len;
378 if (PPP_CipherFinal(ctx, cipher+offset, &cipher_len)) {
380 if (memcmp(cipher, expect, 80) == 0) {
387 PPP_CIPHER_CTX_free(ctx);
394 int test_des_decrypt()
396 PPP_CIPHER_CTX* ctx = NULL;
399 unsigned char key[8] = {
400 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
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
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
429 unsigned char plain[80] = {};
433 ctx = PPP_CIPHER_CTX_new();
436 if (PPP_CipherInit(ctx, PPP_des_ecb(), key, NULL, 0)) {
438 if (PPP_CipherUpdate(ctx, plain, &outlen, cipher, sizeof(cipher))) {
442 if (PPP_CipherFinal(ctx, plain+offset, &outlen)) {
444 if (memcmp(plain, expect, 80) == 0) {
451 PPP_CIPHER_CTX_free(ctx);
457 int main(int argc, char *argv[])
461 if (!PPP_crypto_init()) {
462 printf("Couldn't initialize crypto test\n");
467 printf("MD4 test failed\n");
472 printf("MD5 test failed\n");
477 printf("SHA test failed\n");
481 if (!test_des_encrypt()) {
482 printf("DES encryption test failed\n");
486 if (!test_des_decrypt()) {
487 printf("DES decryption test failed\n");
491 if (!PPP_crypto_deinit()) {
492 printf("Couldn't deinitialize crypto test\n");