diff options
author | Eivind Næss <eivnaes@yahoo.com> | 2023-01-20 22:12:58 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-21 17:12:58 +1100 |
commit | ba7f7e053daae846a54a1d08d3d133a5f1266ace (patch) | |
tree | 3da27cf3ca6d6eb76e3f9a05db4c5676591d5002 /pppd/crypto.c | |
parent | 76016e1b948b7d9675b4e0750d1f943d96d9523b (diff) | |
download | ppp-ba7f7e053daae846a54a1d08d3d133a5f1266ace.tar.gz |
Header file reorganization and cleaning up the public API for pppd version 2.5.0 (#379)
This commit does several things, being a squash-and-merge of a series
of changes; squashed in order not to break bisection.
* Clean up pppd.h, moving declarations that should only be accessed by
pppd code (not by users of pppd) to a new pppd-private.h. Also,
other parts of pppd.h were moved to multilink.h, chap.h, eap.h,
eui64.h, and a new options.h.
* Provide an API for access to data that is needed by plugins (in no
particular order):
- ifname
- ifunit
- remote_name
- remote_number
- peer_authname
- status (now called "code" internally)
- phase
- doing_multilink
- multilink_master
- idle_time_limit
- link_connect_time
- max_connect_time
- link_stats
- ipparam
- hostname
- got_sigterm
- got_sigusr2
- got_sighup
- session_number
- maxoctets
- maxoctets_dir
- debug
- persist
- devnam
- modem
- peer_authname
- sync_serial
* Update the version number to 2.5.0.
* Detect availability of stddef.h and stdarg.h.
* Rename some headers:
- pppcrypt.c/h to crypto_ms.c/h
- ppp-crypto.c/h to crypto.c/h
- ppp-crypto-priv.h to crypto-priv.h
- chap-new.c/h to chap.c/h
* Remove chap-md5.h, crypto-priv.h, eap-tls.h, etc. from the list of
header files to be installed.
* Provide typedefs for the hook functions.
* Provide a typedef for the "phase" variable.
* Provide a typedef for the link statistics array.
* Remove the option_t typedef.
* Rename the following functions by adding a "ppp_" prefix (with the
intention that these are a "public" API for use by plugins):
- option_error
- add_options
- int_option,
- options_from_file
- script_setenv
- bad_ip_adrs,
- netif_get/set_mtu (renamed to ppp_get/set_mtu)
- get_time
- timeout
- untimeout
- safe_fork
- sys_close
- set_session_number
- update_link_stats (renamed to ppp_get_link_stats)
- add_notifier (renamed to ppp_add_notify)
- remove_notifier (renamed to ppp_del_notify)
- generic_[dis]establish_ppp (to ppp_generic_[dis]establish)
* Rename ppp_devnam to ppp_devname.
* Rename ppp_available() to ppp_check_kernel_support().
* Use unsigned char instead of u_char, unsigned short instead of
u_short, uint32_t instead of u_int32_t.
* Add const to some declarations
* Update comments
* Change the interface for notifiers to use an enum to identify which
notifier is to be modified.
* Provide an API for getting the path to a file, with an enum to
identify different types of file.
* Link plugins with the -DPLUGIN flag
[paulus@ozlabs.org - wrote commit message]
Signed-off-by: Eivind Næss <eivnaes@yahoo.com>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Diffstat (limited to 'pppd/crypto.c')
-rw-r--r-- | pppd/crypto.c | 499 |
1 files changed, 499 insertions, 0 deletions
diff --git a/pppd/crypto.c b/pppd/crypto.c new file mode 100644 index 0000000..905f11d --- /dev/null +++ b/pppd/crypto.c @@ -0,0 +1,499 @@ +/* ppp-crypto.c - Generic API for access to crypto/digest functions. + * + * Copyright (c) 2022 Eivind Næss. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <string.h> + +#include "crypto.h" +#include "crypto-priv.h" + +#ifdef PPP_WITH_OPENSSL +#include <openssl/opensslv.h> +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include <openssl/provider.h> +struct crypto_ctx { + + OSSL_PROVIDER *legacy; + OSSL_PROVIDER *provider; +} g_crypto_ctx; +#endif + +PPP_MD_CTX *PPP_MD_CTX_new() +{ + return (PPP_MD_CTX*) calloc(1, sizeof(PPP_MD_CTX)); +} + +void PPP_MD_CTX_free(PPP_MD_CTX* ctx) +{ + if (ctx) { + if (ctx->md.clean_fn) { + ctx->md.clean_fn(ctx); + } + free(ctx); + } +} + +int PPP_DigestInit(PPP_MD_CTX *ctx, const PPP_MD *type) +{ + if (ctx) { + ctx->md = *type; + if (ctx->md.init_fn) { + return ctx->md.init_fn(ctx); + } + } + return 0; +} + +int PPP_DigestUpdate(PPP_MD_CTX *ctx, const void *data, size_t length) +{ + if (ctx && ctx->md.update_fn) { + return ctx->md.update_fn(ctx, data, length); + } + return 0; +} + +int PPP_DigestFinal(PPP_MD_CTX *ctx, unsigned char *out, unsigned int *outlen) +{ + if (ctx && ctx->md.final_fn) { + return ctx->md.final_fn(ctx, out, outlen); + } + return 0; +} + +PPP_CIPHER_CTX *PPP_CIPHER_CTX_new(void) +{ + return calloc(1, sizeof(PPP_CIPHER_CTX)); +} + +void PPP_CIPHER_CTX_free(PPP_CIPHER_CTX *ctx) +{ + if (ctx) { + if (ctx->cipher.clean_fn) { + ctx->cipher.clean_fn(ctx); + } + memset(ctx->iv, 0, sizeof(ctx->iv)); + memset(ctx->key, 0, sizeof(ctx->key)); + free(ctx); + } +} + +int PPP_CipherInit(PPP_CIPHER_CTX *ctx, const PPP_CIPHER *cipher, const unsigned char *key, const unsigned char *iv, int encr) +{ + if (ctx && cipher) { + ctx->is_encr = encr; + ctx->cipher = *cipher; + if (ctx->cipher.init_fn) { + ctx->cipher.init_fn(ctx, key, iv); + } + return 1; + } + return 0; +} + +int PPP_CipherUpdate(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl) +{ + if (ctx && ctx->cipher.update_fn) { + return ctx->cipher.update_fn(ctx, out, outl, in, inl); + } + return 0; +} + +int PPP_CipherFinal(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ + if (ctx && ctx->cipher.final_fn) { + return ctx->cipher.final_fn(ctx, out, outl); + } + return 0; +} + +int PPP_crypto_init() +{ + int retval = 0; + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + g_crypto_ctx.legacy = OSSL_PROVIDER_load(NULL, "legacy"); + if (g_crypto_ctx.legacy == NULL) + { + goto done; + } + + g_crypto_ctx.provider = OSSL_PROVIDER_load(NULL, "default"); + if (g_crypto_ctx.provider == NULL) + { + goto done; + } +#endif + retval = 1; + +done: + + return retval; +} + +int PPP_crypto_deinit() +{ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + if (g_crypto_ctx.legacy) { + OSSL_PROVIDER_unload(g_crypto_ctx.legacy); + g_crypto_ctx.legacy = NULL; + } + + if (g_crypto_ctx.provider) { + OSSL_PROVIDER_unload(g_crypto_ctx.provider); + g_crypto_ctx.provider = NULL; + } +#endif + return 1; +} + +#ifdef UNIT_TEST +#include <stdio.h> + +int test_md4() +{ + PPP_MD_CTX* ctx = NULL; + int success = 0; + + unsigned char data[84] = { + 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, + 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, + 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, + 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x2e + }; + + unsigned int hash_len; + unsigned char hash[MD4_DIGEST_LENGTH]; + unsigned char result[MD4_DIGEST_LENGTH] = { + 0x58, 0xcb, 0x37, 0x91, 0x1d, 0x06, 0x7b, 0xdf, + 0xfd, 0x48, 0x6d, 0x87, 0x4a, 0x35, 0x5b, 0xd4 + }; + + ctx = PPP_MD_CTX_new(); + if (ctx) { + + if (PPP_DigestInit(ctx, PPP_md4())) { + + if (PPP_DigestUpdate(ctx, &data, sizeof(data))) { + + hash_len = sizeof(hash); + if (PPP_DigestFinal(ctx, hash, &hash_len)) { + + if (memcmp(hash, result, MD4_DIGEST_LENGTH) == 0) { + success = 1; + } + } + } + } + PPP_MD_CTX_free(ctx); + } + + return success; +} + +int test_md5() +{ + PPP_MD_CTX* ctx = NULL; + int success = 0; + + unsigned char data[84] = { + 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, + 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, + 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, + 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x2e + }; + + unsigned int hash_len; + unsigned char hash[MD5_DIGEST_LENGTH]; + unsigned char result[MD5_DIGEST_LENGTH] = { + 0x8b, 0xe3, 0x5e, 0x2c, 0x9f, 0x95, 0xbf, 0x4e, + 0x16, 0xe4, 0x53, 0xbe, 0x52, 0xf4, 0xbc, 0x4e + }; + + ctx = PPP_MD_CTX_new(); + if (ctx) { + + if (PPP_DigestInit(ctx, PPP_md5())) { + + if (PPP_DigestUpdate(ctx, &data, sizeof(data))) { + + hash_len = sizeof(hash); + if (PPP_DigestFinal(ctx, hash, &hash_len)) { + + if (memcmp(hash, result, MD5_DIGEST_LENGTH) == 0) { + success = 1; + } + } + } + } + PPP_MD_CTX_free(ctx); + } + + return success; +} + +int test_sha() +{ + PPP_MD_CTX* ctx = NULL; + int success = 0; + + unsigned char data[84] = { + 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, + 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, + 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, + 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x2e + }; + + unsigned int hash_len; + unsigned char hash[SHA_DIGEST_LENGTH]; + unsigned char result[SHA_DIGEST_LENGTH] = { + 0xa8, 0x03, 0xae, 0x21, 0x30, 0xd8, 0x40, 0xbe, + 0x27, 0xa3, 0x47, 0xc7, 0x7a, 0x90, 0xe6, 0xa3, + 0x5b, 0xd5, 0x0e, 0x45 + }; + + ctx = PPP_MD_CTX_new(); + if (ctx) { + + if (PPP_DigestInit(ctx, PPP_sha1())) { + + if (PPP_DigestUpdate(ctx, &data, sizeof(data))) { + + hash_len = sizeof(hash); + if (PPP_DigestFinal(ctx, hash, &hash_len)) { + + if (memcmp(hash, result, SHA_DIGEST_LENGTH) == 0) { + success = 1; + } + } + } + } + PPP_MD_CTX_free(ctx); + } + + return success; +} + +int test_des_encrypt() +{ + PPP_CIPHER_CTX* ctx = NULL; + int success = 0; + + unsigned char key[8] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + + unsigned char plain[80] = { + 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, + 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, + 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, + 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20 + }; + unsigned char expect[80] = { + 0x45, 0xdb, 0x80, 0x45, 0x16, 0xd0, 0x6d, 0x60, + 0x92, 0x23, 0x4b, 0xd3, 0x9d, 0x36, 0xb8, 0x1a, + 0xa4, 0x1a, 0xf7, 0xb1, 0x60, 0xfb, 0x74, 0x16, + 0xa6, 0xdc, 0xe1, 0x14, 0xb7, 0xed, 0x48, 0x5a, + 0x2b, 0xed, 0x68, 0x9d, 0x19, 0xd6, 0xb1, 0xb8, + 0x91, 0xff, 0xea, 0x62, 0xac, 0xe7, 0x49, 0xdd, + 0xfa, 0x4d, 0xa4, 0x01, 0x3f, 0xea, 0xca, 0xb4, + 0xb6, 0xdc, 0xd3, 0x04, 0x45, 0x07, 0x74, 0xed, + 0xa6, 0xdc, 0xe1, 0x14, 0xb7, 0xed, 0x48, 0x5a, + 0xbb, 0x9b, 0x13, 0x31, 0xf4, 0xa9, 0x32, 0x49 + }; + + unsigned char cipher[80] = {}; + int cipher_len = 0; + int offset = 0; + + + ctx = PPP_CIPHER_CTX_new(); + if (ctx) { + + if (PPP_CipherInit(ctx, PPP_des_ecb(), key, NULL, 1)) { + + if (PPP_CipherUpdate(ctx, cipher, &cipher_len, plain, sizeof(plain))) { + + offset += cipher_len; + + if (PPP_CipherFinal(ctx, cipher+offset, &cipher_len)) { + + if (memcmp(cipher, expect, 80) == 0) { + + success = 1; + } + } + } + } + PPP_CIPHER_CTX_free(ctx); + } + + return success; +} + + +int test_des_decrypt() +{ + PPP_CIPHER_CTX* ctx = NULL; + int success = 0; + + unsigned char key[8] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + + unsigned char cipher[80] = { + 0x45, 0xdb, 0x80, 0x45, 0x16, 0xd0, 0x6d, 0x60, + 0x92, 0x23, 0x4b, 0xd3, 0x9d, 0x36, 0xb8, 0x1a, + 0xa4, 0x1a, 0xf7, 0xb1, 0x60, 0xfb, 0x74, 0x16, + 0xa6, 0xdc, 0xe1, 0x14, 0xb7, 0xed, 0x48, 0x5a, + 0x2b, 0xed, 0x68, 0x9d, 0x19, 0xd6, 0xb1, 0xb8, + 0x91, 0xff, 0xea, 0x62, 0xac, 0xe7, 0x49, 0xdd, + 0xfa, 0x4d, 0xa4, 0x01, 0x3f, 0xea, 0xca, 0xb4, + 0xb6, 0xdc, 0xd3, 0x04, 0x45, 0x07, 0x74, 0xed, + 0xa6, 0xdc, 0xe1, 0x14, 0xb7, 0xed, 0x48, 0x5a, + 0xbb, 0x9b, 0x13, 0x31, 0xf4, 0xa9, 0x32, 0x49 + }; + + unsigned char expect[80] = { + 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, + 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, + 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, + 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20 + }; + + unsigned char plain[80] = {}; + int outlen = 0; + int offset = 0; + + ctx = PPP_CIPHER_CTX_new(); + if (ctx) { + + if (PPP_CipherInit(ctx, PPP_des_ecb(), key, NULL, 0)) { + + if (PPP_CipherUpdate(ctx, plain, &outlen, cipher, sizeof(cipher))) { + + offset += outlen; + + if (PPP_CipherFinal(ctx, plain+offset, &outlen)) { + + if (memcmp(plain, expect, 80) == 0) { + + success = 1; + } + } + } + } + PPP_CIPHER_CTX_free(ctx); + } + + return success; +} + +int main(int argc, char *argv[]) +{ + int failure = 0; + + if (!PPP_crypto_init()) { + printf("Couldn't initialize crypto test\n"); + return -1; + } + + if (!test_md4()) { + printf("MD4 test failed\n"); + failure++; + } + + if (!test_md5()) { + printf("MD5 test failed\n"); + failure++; + } + + if (!test_sha()) { + printf("SHA test failed\n"); + failure++; + } + + if (!test_des_encrypt()) { + printf("DES encryption test failed\n"); + failure++; + } + + if (!test_des_decrypt()) { + printf("DES decryption test failed\n"); + failure++; + } + + if (!PPP_crypto_deinit()) { + printf("Couldn't deinitialize crypto test\n"); + return -1; + } + + return failure; +} + +#endif |