From: Paul Mackerras Date: Fri, 9 Sep 2022 02:07:20 +0000 (+1000) Subject: Merge pull request #366 from pali/rtnetlink-register X-Git-Tag: ppp-2.5.0~24 X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=35198adc7f3c1f0c1e3437f983e7f3ac96477997;hp=089687fbcc6524809ae9f4b2f8145fe3c2a91147 Merge pull request #366 from pali/rtnetlink-register pppd: Retry registering interface when on rtnetlink -EBUSY error --- diff --git a/configure.ac b/configure.ac index 640f70e..7b4c842 100644 --- a/configure.ac +++ b/configure.ac @@ -221,7 +221,9 @@ AC_SUBST(PPPD_LOGFILE_DIR) # # Check for OpenSSL AX_CHECK_OPENSSL -AM_CONDITIONAL(WITH_OPENSSL, test "x${with_openssl}" != "xno") +AM_CONDITIONAL(PPP_WITH_OPENSSL, test "x${with_openssl}" != "xno") +AM_COND_IF([PPP_WITH_OPENSSL], + AC_DEFINE([PPP_WITH_OPENSSL], 1, [PPP is compiled with openssl support])) # # Check if OpenSSL has compiled in support for various ciphers @@ -236,29 +238,20 @@ AS_IF([test "x${with_openssl}" != "xno" ], [ ]) AM_CONDITIONAL([OPENSSL_HAVE_MD4], test "x${ac_cv_openssl_md4}" = "xyes") -AM_COND_IF([OPENSSL_HAVE_MD4],, - AC_DEFINE([USE_MD4], 1, [Use MD4 included with pppd])) +AM_COND_IF([OPENSSL_HAVE_MD4], + AC_DEFINE([OPENSSL_HAVE_MD4], 1, [Use MD4 included with openssl])) AM_CONDITIONAL([OPENSSL_HAVE_MD5], test "x${ac_cv_openssl_md5}" = "xyes") -AM_COND_IF([OPENSSL_HAVE_MD5],, - AC_DEFINE([USE_MD5], 1, [Use MD5 included with pppd])) +AM_COND_IF([OPENSSL_HAVE_MD5], + AC_DEFINE([OPENSSL_HAVE_MD5], 1, [Use MD5 included with openssl])) AM_CONDITIONAL([OPENSSL_HAVE_SHA], test "x${ac_cv_openssl_sha}" = "xyes") -AM_COND_IF([OPENSSL_HAVE_SHA],, - AC_DEFINE([USE_SHA], 1, [Use SHA included with pppd])) +AM_COND_IF([OPENSSL_HAVE_SHA], + AC_DEFINE([OPENSSL_HAVE_SHA], 1, [Use SHA included with openssl])) AM_CONDITIONAL([OPENSSL_HAVE_DES], test "x${ac_cv_openssl_des}" = "xyes") -AM_COND_IF([OPENSSL_HAVE_DES],, - AC_DEFINE([USE_CRYPT], 1, [Use DES included with pppd])) - -# -# If OpenSSL doesn't support DES, then use the one from libcrypt (glibc dropped support for this in 2.27). -AS_IF([test "x${ac_cv_openssl_des}" = "xno" ], [ - AC_CHECK_LIB([crypt], [encrypt], - [LIBS="$LIBS -lcrypt"], - [AC_MSG_ERROR([OpenSSL not found or does not support DES, and libcrypt also doesn't support encrypt])] - ) -]) +AM_COND_IF([OPENSSL_HAVE_DES], + AC_DEFINE([OPENSSL_HAVE_DES], 1, [Use DES included with openssl])) # # With libsrp support diff --git a/pppd/.gitignore b/pppd/.gitignore index 5666003..895bf37 100644 --- a/pppd/.gitignore +++ b/pppd/.gitignore @@ -1 +1,2 @@ pppd +srp-entry diff --git a/pppd/Makefile.am b/pppd/Makefile.am index b392f2e..55d926b 100644 --- a/pppd/Makefile.am +++ b/pppd/Makefile.am @@ -2,7 +2,7 @@ sbin_PROGRAMS = pppd dist_man8_MANS = pppd.8 check_PROGRAMS = -utest_chap_SOURCES = chap_ms.c pppcrypt.c utils.c +utest_chap_SOURCES = chap_ms.c utils.c pppcrypt.c utest_chap_CPPFLAGS = -DUNIT_TEST utest_chap_LDFLAGS = @@ -10,6 +10,16 @@ utest_peap_SOURCES = peap.c utils.c mppe.c utest_peap_CPPFLAGS = -DUNIT_TEST utest_peap_LDFLAGS = +utest_crypto_SOURCES = ppp-crypto.c +utest_crypto_CPPFLAGS = -DUNIT_TEST +utest_crypto_LDFLAGS = + +utest_pppcrypt_SOURCES = pppcrypt.c +utest_pppcrypt_CPPFLAGS = -DUNIT_TEST_PPPCRYPT +utest_pppcrypt_LDFLAGS = + +check_PROGRAMS += utest_crypto + if WITH_SRP sbin_PROGRAMS += srp-entry dist_man8_MANS += srp-entry.8 @@ -34,16 +44,15 @@ pppd_include_HEADERS = \ ipv6cp.h \ lcp.h \ magic.h \ - md4.h \ - md5.h \ mppe.h \ pathnames.h \ peap.h \ - pppcrypt.h \ pppd.h \ pppdconf.h \ + pppcrypt.h \ + ppp-crypto.h \ + ppp-crypto-priv.h \ session.h \ - sha1.h \ spinlock.h \ tls.h \ tdb.h \ @@ -84,12 +93,13 @@ pppd_LIBS += -lsocket -lnsl endif if PPP_WITH_CHAPMS -pppd_SOURCES += chap_ms.c -pppd_SOURCES += pppcrypt.c +pppd_SOURCES += chap_ms.c pppcrypt.c check_PROGRAMS += utest_chap +check_PROGRAMS += utest_pppcrypt else if WITH_SRP pppd_SOURCES += pppcrypt.c +check_PROGRAMS += utest_pppcrypt endif endif @@ -147,27 +157,19 @@ check_PROGRAMS += utest_peap endif noinst_LTLIBRARIES = libppp_crypt.la -libppp_crypt_la_SOURCES= +libppp_crypt_la_SOURCES=ppp-crypto.c ppp-md5.c ppp-md4.c ppp-sha1.c ppp-des.c -if !WITH_OPENSSL -libppp_crypt_la_SOURCES += md4.c md5.c sha1.c -else +if PPP_WITH_OPENSSL libppp_crypt_la_CPPFLAGS=$(OPENSSL_INCLUDES) libppp_crypt_la_LDFLAGS=$(OPENSSL_LDFLAGS) libppp_crypt_la_LIBADD=$(OPENSSL_LIBS) -if !OPENSSL_HAVE_SHA -libppp_crypt_la_SOURCES += sha1.c -endif -if !OPENSSL_HAVE_MD5 -libppp_crypt_la_SOURCES += md5.c -endif -if !OPENSSL_HAVE_MD4 -libppp_crypt_la_SOURCES += md4.c -endif endif utest_peap_LDADD = libppp_crypt.la utest_chap_LDADD = libppp_crypt.la +utest_crypto_LDADD = libppp_crypt.la +utest_pppcrypt_LDADD = libppp_crypt.la + pppd_LIBS += libppp_crypt.la if WITH_SYSTEMD diff --git a/pppd/chap-md5.c b/pppd/chap-md5.c index 000f880..8bcbbba 100644 --- a/pppd/chap-md5.c +++ b/pppd/chap-md5.c @@ -40,9 +40,8 @@ #include "chap-new.h" #include "chap-md5.h" #include "magic.h" -#include "md5.h" +#include "ppp-crypto.h" -#define MD5_HASH_SIZE 16 #define MD5_MIN_CHALLENGE 16 #define MD5_MAX_CHALLENGE 24 @@ -63,27 +62,43 @@ chap_md5_verify_response(int id, char *name, unsigned char *challenge, unsigned char *response, char *message, int message_space) { - MD5_CTX ctx; unsigned char idbyte = id; - unsigned char hash[MD5_HASH_SIZE]; + unsigned char hash[MD5_DIGEST_LENGTH]; + unsigned int hash_len = MD5_DIGEST_LENGTH; int challenge_len, response_len; + bool success = 0; challenge_len = *challenge++; response_len = *response++; - if (response_len == MD5_HASH_SIZE) { + if (response_len == MD5_DIGEST_LENGTH) { + /* Generate hash of ID, secret, challenge */ - MD5_Init(&ctx); - MD5_Update(&ctx, &idbyte, 1); - MD5_Update(&ctx, secret, secret_len); - MD5_Update(&ctx, challenge, challenge_len); - MD5_Final(hash, &ctx); - - /* Test if our hash matches the peer's response */ - if (memcmp(hash, response, MD5_HASH_SIZE) == 0) { - slprintf(message, message_space, "Access granted"); - return 1; + PPP_MD_CTX* ctx = PPP_MD_CTX_new(); + if (ctx) { + + if (PPP_DigestInit(ctx, PPP_md5())) { + + if (PPP_DigestUpdate(ctx, &idbyte, 1)) { + + if (PPP_DigestUpdate(ctx, secret, secret_len)) { + + if (PPP_DigestUpdate(ctx, challenge, challenge_len)) { + + if (PPP_DigestFinal(ctx, hash, &hash_len)) { + + success = 1; + } + } + } + } + } + PPP_MD_CTX_free(ctx); } } + if (success && memcmp(hash, response, hash_len) == 0) { + slprintf(message, message_space, "Access granted"); + return 1; + } slprintf(message, message_space, "Access denied"); return 0; } @@ -93,16 +108,31 @@ chap_md5_make_response(unsigned char *response, int id, char *our_name, unsigned char *challenge, char *secret, int secret_len, unsigned char *private) { - MD5_CTX ctx; unsigned char idbyte = id; int challenge_len = *challenge++; + int hash_len = MD5_DIGEST_LENGTH; - MD5_Init(&ctx); - MD5_Update(&ctx, &idbyte, 1); - MD5_Update(&ctx, (u_char *)secret, secret_len); - MD5_Update(&ctx, challenge, challenge_len); - MD5_Final(&response[1], &ctx); - response[0] = MD5_HASH_SIZE; + PPP_MD_CTX* ctx = PPP_MD_CTX_new(); + if (ctx) { + + if (PPP_DigestInit(ctx, PPP_md5())) { + + if (PPP_DigestUpdate(ctx, &idbyte, 1)) { + + if (PPP_DigestUpdate(ctx, secret, secret_len)) { + + if (PPP_DigestUpdate(ctx, challenge, challenge_len)) { + + if (PPP_DigestFinal(ctx, &response[1], &hash_len)) { + + response[0] = hash_len; + } + } + } + } + } + PPP_MD_CTX_free(ctx); + } } static struct chap_digest_type md5_digest = { diff --git a/pppd/chap_ms.c b/pppd/chap_ms.c index 8e59280..704052f 100644 --- a/pppd/chap_ms.c +++ b/pppd/chap_ms.c @@ -96,19 +96,18 @@ #include "pppd.h" #include "chap-new.h" #include "chap_ms.h" -#include "md4.h" -#include "sha1.h" -#include "pppcrypt.h" #include "magic.h" #include "mppe.h" +#include "ppp-crypto.h" +#include "pppcrypt.h" #ifdef UNIT_TEST #undef PPP_WITH_MPPE #endif static void ascii2unicode (char[], int, u_char[]); -static void NTPasswordHash (u_char *, int, u_char[MD4_SIGNATURE_SIZE]); -static void ChallengeResponse (u_char *, u_char *, u_char[24]); +static void NTPasswordHash (u_char *, int, unsigned char *); +static int ChallengeResponse (u_char *, u_char *, u_char*); static void ChapMS_NT (u_char *, char *, int, u_char[24]); static void ChapMS2_NT (u_char *, u_char[16], char *, char *, int, u_char[24]); @@ -504,31 +503,31 @@ print_msg: free(msg); } -static void +static int ChallengeResponse(u_char *challenge, - u_char PasswordHash[MD4_SIGNATURE_SIZE], - u_char response[24]) + u_char *PasswordHash, + u_char *response) { - u_char ZPasswordHash[21]; + u_char ZPasswordHash[21]; + PPP_CIPHER_CTX *ctx; BZERO(ZPasswordHash, sizeof(ZPasswordHash)); - BCOPY(PasswordHash, ZPasswordHash, MD4_SIGNATURE_SIZE); + BCOPY(PasswordHash, ZPasswordHash, MD4_DIGEST_LENGTH); #if 0 dbglog("ChallengeResponse - ZPasswordHash %.*B", sizeof(ZPasswordHash), ZPasswordHash); #endif - (void) DesSetkey(ZPasswordHash + 0); - DesEncrypt(challenge, response + 0); - (void) DesSetkey(ZPasswordHash + 7); - DesEncrypt(challenge, response + 8); - (void) DesSetkey(ZPasswordHash + 14); - DesEncrypt(challenge, response + 16); + if (DesEncrypt(challenge, ZPasswordHash + 0, response + 0) && + DesEncrypt(challenge, ZPasswordHash + 7, response + 8) && + DesEncrypt(challenge, ZPasswordHash + 14, response + 16)) + return 1; #if 0 dbglog("ChallengeResponse - response %.24B", response); #endif + return 0; } void @@ -536,8 +535,9 @@ ChallengeHash(u_char PeerChallenge[16], u_char *rchallenge, char *username, u_char Challenge[8]) { - SHA1_CTX sha1Context; - u_char sha1Hash[SHA1_SIGNATURE_SIZE]; + PPP_MD_CTX* ctx; + u_char hash[SHA_DIGEST_LENGTH]; + int hash_len; char *user; /* remove domain from "domain\username" */ @@ -545,14 +545,30 @@ ChallengeHash(u_char PeerChallenge[16], u_char *rchallenge, ++user; else user = username; + + ctx = PPP_MD_CTX_new(); + if (ctx != NULL) { + + if (PPP_DigestInit(ctx, PPP_sha1())) { + + if (PPP_DigestUpdate(ctx, PeerChallenge, 16)) { + + if (PPP_DigestUpdate(ctx, rchallenge, 16)) { - SHA1_Init(&sha1Context); - SHA1_Update(&sha1Context, PeerChallenge, 16); - SHA1_Update(&sha1Context, rchallenge, 16); - SHA1_Update(&sha1Context, (unsigned char *)user, strlen(user)); - SHA1_Final(sha1Hash, &sha1Context); + if (PPP_DigestUpdate(ctx, user, strlen(user))) { + + hash_len = SHA_DIGEST_LENGTH; + if (PPP_DigestFinal(ctx, hash, &hash_len)) { - BCOPY(sha1Hash, Challenge, 8); + BCOPY(hash, Challenge, 8); + } + } + } + } + } + + PPP_MD_CTX_free(ctx); + } } /* @@ -573,28 +589,22 @@ ascii2unicode(char ascii[], int ascii_len, u_char unicode[]) } static void -NTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE]) +NTPasswordHash(u_char *secret, int secret_len, unsigned char* hash) { -#if defined(__NetBSD__) || !defined(USE_MD4) - /* NetBSD uses the libc md4 routines which take bytes instead of bits */ - int mdlen = secret_len; -#else - int mdlen = secret_len * 8; -#endif - MD4_CTX md4Context; - - MD4Init(&md4Context); -#if !defined(USE_MD4) - /* Internal MD4Update can take at most 64 bytes at a time */ - while (mdlen > 512) { - MD4Update(&md4Context, secret, 512); - secret += 64; - mdlen -= 512; - } -#endif - MD4Update(&md4Context, secret, mdlen); - MD4Final(hash, &md4Context); + PPP_MD_CTX* ctx = PPP_MD_CTX_new(); + if (ctx != NULL) { + + if (PPP_DigestInit(ctx, PPP_md4())) { + + if (PPP_DigestUpdate(ctx, secret, secret_len)) { + int hash_len = MD4_DIGEST_LENGTH; + PPP_DigestFinal(ctx, hash, &hash_len); + } + } + + PPP_MD_CTX_free(ctx); + } } static void @@ -602,7 +612,7 @@ ChapMS_NT(u_char *rchallenge, char *secret, int secret_len, u_char NTResponse[24]) { u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHash[MD4_DIGEST_LENGTH]; /* Hash the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); @@ -616,7 +626,7 @@ ChapMS2_NT(u_char *rchallenge, u_char PeerChallenge[16], char *username, char *secret, int secret_len, u_char NTResponse[24]) { u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHash[MD4_DIGEST_LENGTH]; u_char Challenge[8]; ChallengeHash(PeerChallenge, rchallenge, username, Challenge); @@ -637,7 +647,7 @@ ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len, { int i; u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ - u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHash[MD4_DIGEST_LENGTH]; /* LANMan password is case insensitive */ BZERO(UcasePassword, sizeof(UcasePassword)); @@ -653,10 +663,10 @@ ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len, void -GenerateAuthenticatorResponse(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], - u_char NTResponse[24], u_char PeerChallenge[16], - u_char *rchallenge, char *username, - u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) +GenerateAuthenticatorResponse(unsigned char* PasswordHashHash, + unsigned char *NTResponse, unsigned char *PeerChallenge, + unsigned char *rchallenge, char *username, + unsigned char *authResponse) { /* * "Magic" constants used in response generation, from RFC 2759. @@ -674,27 +684,58 @@ GenerateAuthenticatorResponse(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], 0x6E }; int i; - SHA1_CTX sha1Context; - u_char Digest[SHA1_SIGNATURE_SIZE]; + PPP_MD_CTX *ctx; + u_char Digest[SHA_DIGEST_LENGTH]; + int hash_len; u_char Challenge[8]; - SHA1_Init(&sha1Context); - SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - SHA1_Update(&sha1Context, NTResponse, 24); - SHA1_Update(&sha1Context, Magic1, sizeof(Magic1)); - SHA1_Final(Digest, &sha1Context); + ctx = PPP_MD_CTX_new(); + if (ctx != NULL) { + + if (PPP_DigestInit(ctx, PPP_sha1())) { + + if (PPP_DigestUpdate(ctx, PasswordHashHash, MD4_DIGEST_LENGTH)) { + + if (PPP_DigestUpdate(ctx, NTResponse, 24)) { + if (PPP_DigestUpdate(ctx, Magic1, sizeof(Magic1))) { + + hash_len = sizeof(Digest); + PPP_DigestFinal(ctx, Digest, &hash_len); + } + } + } + } + PPP_MD_CTX_free(ctx); + } + ChallengeHash(PeerChallenge, rchallenge, username, Challenge); - SHA1_Init(&sha1Context); - SHA1_Update(&sha1Context, Digest, sizeof(Digest)); - SHA1_Update(&sha1Context, Challenge, sizeof(Challenge)); - SHA1_Update(&sha1Context, Magic2, sizeof(Magic2)); - SHA1_Final(Digest, &sha1Context); + ctx = PPP_MD_CTX_new(); + if (ctx != NULL) { + + if (PPP_DigestInit(ctx, PPP_sha1())) { + + if (PPP_DigestUpdate(ctx, Digest, sizeof(Digest))) { + + if (PPP_DigestUpdate(ctx, Challenge, sizeof(Challenge))) { + + if (PPP_DigestUpdate(ctx, Magic2, sizeof(Magic2))) { + + hash_len = sizeof(Digest); + PPP_DigestFinal(ctx, Digest, &hash_len); + } + } + } + } + + PPP_MD_CTX_free(ctx); + } /* Convert to ASCII hex string. */ - for (i = 0; i < MAX((MS_AUTH_RESPONSE_LENGTH / 2), sizeof(Digest)); i++) - sprintf((char *)&authResponse[i * 2], "%02X", Digest[i]); + for (i = 0; i < MAX((MS_AUTH_RESPONSE_LENGTH / 2), sizeof(Digest)); i++) { + sprintf((char *)&authResponse[i * 2], "%02X", Digest[i]); + } } @@ -706,8 +747,8 @@ GenerateAuthenticatorResponsePlain u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHash[MD4_DIGEST_LENGTH]; + u_char PasswordHashHash[MD4_DIGEST_LENGTH]; /* Hash (x2) the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); @@ -729,8 +770,8 @@ static void Set_Start_Key(u_char *rchallenge, char *secret, int secret_len) { u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHash[MD4_DIGEST_LENGTH]; + u_char PasswordHashHash[MD4_DIGEST_LENGTH]; /* Hash (x2) the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); @@ -747,8 +788,8 @@ static void SetMasterKeys(char *secret, int secret_len, u_char NTResponse[24], int IsServer) { u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHash[MD4_DIGEST_LENGTH]; + u_char PasswordHashHash[MD4_DIGEST_LENGTH]; /* Hash (x2) the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); @@ -874,10 +915,10 @@ void random_bytes(unsigned char *bytes, int len) int test_chap_v1(void) { - char *secret = "TestPassword"; + char *secret = "MyPw"; unsigned char challenge[8] = { - 0x6c, 0x8d, 0x4b, 0xa1, 0x2b, 0x5c, 0x13, 0xc3 + 0x10, 0x2D, 0xB5, 0xDF, 0x08, 0x5D, 0x30, 0x41 }; unsigned char response[MS_CHAP_RESPONSE_LEN] = { }; @@ -886,9 +927,10 @@ int test_chap_v1(void) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x91, 0x09, 0x61, 0x5a, 0x0c, 0xac, 0xac, 0x55, - 0x1f, 0x60, 0xe2, 0x9c, 0x00, 0xac, 0x24, 0xda, - 0x6e, 0xa5, 0x7b, 0xdb, 0x1d, 0x6a, 0x17, 0xc5, + 0x4E, 0x9D, 0x3C, 0x8F, 0x9C, 0xFD, 0x38, 0x5D, + 0x5B, 0xF4, 0xD3, 0x24, 0x67, 0x91, 0x95, 0x6C, + 0xA4, 0xC3, 0x51, 0xAB, 0x40, 0x9A, 0x3D, 0x61, + 0x01 }; @@ -929,6 +971,8 @@ int test_chap_v2(void) { } int main(int argc, char *argv[]) { + + PPP_crypto_init(); if (test_chap_v1()) { printf("CHAPv1 failed\n"); @@ -940,6 +984,8 @@ int main(int argc, char *argv[]) { return -1; } + PPP_crypto_deinit(); + printf("Success\n"); return 0; } diff --git a/pppd/chap_ms.h b/pppd/chap_ms.h index 7b08cff..5397a22 100644 --- a/pppd/chap_ms.h +++ b/pppd/chap_ms.h @@ -35,7 +35,6 @@ #include "pppdconf.h" -#define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */ #define MAX_NT_PASSWORD 256 /* Max (Unicode) chars in an NT pass */ #define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ @@ -81,10 +80,18 @@ void ChapMS2 (u_char *, u_char *, char *, char *, int, void ChallengeHash (u_char[16], u_char *, char *, u_char[8]); -void GenerateAuthenticatorResponse(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], - u_char NTResponse[24], u_char PeerChallenge[16], - u_char *rchallenge, char *username, - u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]); + +/** + * PasswordHashHash - 16 bytes representing the NT Password Hash Hash + * NTResponse - 24 bytes represending the NTResponse parameter + * PeerChallenge - 16 bytes challange for peer + * rchallenge - 16 bytes challenge provided by peer + * authResponse - 24 + 1 byte to store the authenticator response + */ +void GenerateAuthenticatorResponse(unsigned char *PasswordHashHash, + unsigned char *NTResponse, unsigned char *PeerChallenge, + unsigned char *rchallenge, char *username, + unsigned char *authResponse); void chapms_init(void); diff --git a/pppd/eap.c b/pppd/eap.c index 305a838..4dd3123 100644 --- a/pppd/eap.c +++ b/pppd/eap.c @@ -65,7 +65,8 @@ #include "pppd.h" #include "pathnames.h" -#include "md5.h" +#include "ppp-crypto.h" +#include "pppcrypt.h" #include "eap.h" #ifdef PPP_WITH_PEAP #include "peap.h" @@ -78,13 +79,8 @@ #include #include #include -#include "pppcrypt.h" #endif /* PPP_WITH_SRP */ -#ifndef SHA_DIGESTSIZE -#define SHA_DIGESTSIZE 20 -#endif - #ifdef PPP_WITH_EAPTLS #include "eap-tls.h" #endif /* PPP_WITH_EAPTLS */ @@ -333,24 +329,33 @@ eap_send_success(eap_state *esp) * date. */ static bool -pncrypt_setkey(int timeoffs) +pncrypt_getkey(int timeoffs, unsigned char *key, int keylen) { struct tm *tp; char tbuf[9]; - SHA1_CTX ctxt; - u_char dig[SHA_DIGESTSIZE]; + PPP_MD_CTX *ctxt; time_t reftime; if (pn_secret == NULL) return (0); reftime = time(NULL) + timeoffs; tp = localtime(&reftime); - SHA1Init(&ctxt); - SHA1Update(&ctxt, pn_secret, strlen(pn_secret)); - strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp); - SHA1Update(&ctxt, tbuf, strlen(tbuf)); - SHA1Final(dig, &ctxt); - return (DesSetkey(dig)); + + ctxt = PPP_MD_CTX_new(); + if (ctxt) { + + strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp); + + PPP_DigestInit(ctxt, PPP_sha1()); + PPP_DigestUpdate(ctxt, pn_secret, strlen(pn_secret)); + PPP_DigestUpdate(ctxt, tbuf, strlen(tbuf)); + PPP_DigestFinal(ctxt, key, &keylen); + + PPP_MD_CTX_free(ctxt); + return 1; + } + + return (0); } static char base64[] = @@ -435,12 +440,12 @@ static void eap_figure_next_state(eap_state *esp, int status) { #ifdef PPP_WITH_SRP - unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp; + unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp, key[SHA_DIGEST_LENGTH]; struct t_pw tpw; struct t_confent *tce, mytce; char *cp, *cp2; struct t_server *ts; - int id, i, plen, toffs; + int id, i, plen, clen, toffs, keylen; u_char vals[2]; struct b64state bs; #endif /* PPP_WITH_SRP */ @@ -486,11 +491,12 @@ eap_figure_next_state(eap_state *esp, int status) secbuf); toffs = 0; for (i = 0; i < 5; i++) { - pncrypt_setkey(toffs); + pncrypt_getkey(toffs, key, keylen); toffs -= 86400; - if (!DesDecrypt(secbuf, clear)) { + + if (!DesDecrypt(secbuf, key, clear)) { dbglog("no DES here; cannot decode " - "pseudonym"); + "pseudonym"); return; } id = *(unsigned char *)clear; @@ -512,7 +518,7 @@ eap_figure_next_state(eap_state *esp, int status) dp += i; sp = secbuf + 8; while (plen > 0) { - (void) DesDecrypt(sp, dp); + DesDecrypt(sp, key, dp); sp += 8; dp += 8; plen -= 8; @@ -812,10 +818,10 @@ eap_send_request(eap_state *esp) char *str; #ifdef PPP_WITH_SRP struct t_server *ts; - u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp; - int i, j; + u_char clear[8], cipher[8], dig[SHA_DIGEST_LENGTH], *optr, *cp, key[SHA_DIGEST_LENGTH]; + int i, j, diglen, clen, keylen = sizeof(key); struct b64state b64; - SHA1_CTX ctxt; + PPP_MD_CTX *ctxt; #endif /* PPP_WITH_SRP */ /* Handle both initial auth and restart */ @@ -975,10 +981,10 @@ eap_send_request(eap_state *esp) PUTLONG(SRPVAL_EBIT, outp); ts = (struct t_server *)esp->es_server.ea_session; assert(ts != NULL); - BCOPY(t_serverresponse(ts), outp, SHA_DIGESTSIZE); - INCPTR(SHA_DIGESTSIZE, outp); + BCOPY(t_serverresponse(ts), outp, SHA_DIGEST_LENGTH); + INCPTR(SHA_DIGEST_LENGTH, outp); - if (pncrypt_setkey(0)) { + if (pncrypt_getkey(0, key, keylen)) { /* Generate pseudonym */ optr = outp; cp = (unsigned char *)esp->es_server.ea_peer; @@ -988,15 +994,17 @@ eap_send_request(eap_state *esp) BCOPY(cp, clear + 1, j); i -= j; cp += j; - if (!DesEncrypt(clear, cipher)) { + + if (!DesEncrypt(clear, key, cipher)) { dbglog("no DES here; not generating pseudonym"); break; - } + } + BZERO(&b64, sizeof (b64)); outp++; /* space for pseudonym length */ outp += b64enc(&b64, cipher, 8, outp); while (i >= 8) { - (void) DesEncrypt(cp, cipher); + DesEncrypt(cp, key, cipher); outp += b64enc(&b64, cipher, 8, outp); cp += 8; i -= 8; @@ -1008,7 +1016,8 @@ eap_send_request(eap_state *esp) *cp++ = drand48() * 0x100; i++; } - (void) DesEncrypt(clear, cipher); + + DesEncrypt(clear, key, cipher); outp += b64enc(&b64, cipher, 8, outp); } outp += b64flush(&b64, outp); @@ -1016,32 +1025,40 @@ eap_send_request(eap_state *esp) /* Set length and pad out to next 20 octet boundary */ i = outp - optr - 1; *optr = i; - i %= SHA_DIGESTSIZE; + i %= SHA_DIGEST_LENGTH; if (i != 0) { - while (i < SHA_DIGESTSIZE) { + while (i < SHA_DIGEST_LENGTH) { *outp++ = drand48() * 0x100; i++; } } /* Obscure the pseudonym with SHA1 hash */ - SHA1Init(&ctxt); - SHA1Update(&ctxt, &esp->es_server.ea_id, 1); - SHA1Update(&ctxt, esp->es_server.ea_skey, - SESSION_KEY_LEN); - SHA1Update(&ctxt, esp->es_server.ea_peer, - esp->es_server.ea_peerlen); - while (optr < outp) { - SHA1Final(dig, &ctxt); - cp = dig; - while (cp < dig + SHA_DIGESTSIZE) - *optr++ ^= *cp++; - SHA1Init(&ctxt); - SHA1Update(&ctxt, &esp->es_server.ea_id, 1); - SHA1Update(&ctxt, esp->es_server.ea_skey, - SESSION_KEY_LEN); - SHA1Update(&ctxt, optr - SHA_DIGESTSIZE, - SHA_DIGESTSIZE); + ctxt = PPP_MD_CTX_new(); + if (ctxt) { + + PPP_DigestInit(ctxt, PPP_sha1()); + PPP_DigestUpdate(ctxt, &esp->es_server.ea_id, 1); + PPP_DigestUpdate(ctxt, &esp->es_server.ea_skey, + SESSION_KEY_LEN); + PPP_DigestUpdate(ctxt, esp->es_server.ea_peer, + esp->es_server.ea_peerlen); + while (optr < outp) { + diglen = SHA_DIGEST_LENGTH; + PPP_DigestFinal(ctxt, dig, &diglen); + cp = dig; + while (cp < dig + SHA_DIGEST_LENGTH) + *optr++ ^= *cp++; + + PPP_DigestInit(ctxt, PPP_sha1()); + PPP_DigestUpdate(ctxt, &esp->es_server.ea_id, 1); + PPP_DigestUpdate(ctxt, esp->es_server.ea_skey, + SESSION_KEY_LEN); + PPP_DigestUpdate(ctxt, optr - SHA_DIGEST_LENGTH, + SHA_DIGEST_LENGTH); + } + + PPP_MD_CTX_free(ctxt); } } break; @@ -1322,19 +1339,19 @@ eap_chap_response(eap_state *esp, u_char id, u_char *hash, int msglen; outp = outpacket_buf; - + MAKEHEADER(outp, PPP_EAP); PUTCHAR(EAP_RESPONSE, outp); PUTCHAR(id, outp); esp->es_client.ea_id = id; - msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_DIGEST_LENGTH + namelen; PUTSHORT(msglen, outp); PUTCHAR(EAPT_MD5CHAP, outp); - PUTCHAR(MD5_SIGNATURE_SIZE, outp); - BCOPY(hash, outp, MD5_SIGNATURE_SIZE); - INCPTR(MD5_SIGNATURE_SIZE, outp); + PUTCHAR(MD5_DIGEST_LENGTH, outp); + BCOPY(hash, outp, MD5_DIGEST_LENGTH); + INCPTR(MD5_DIGEST_LENGTH, outp); if (namelen > 0) { BCOPY(name, outp, namelen); } @@ -1388,12 +1405,12 @@ eap_srpval_response(eap_state *esp, u_char id, u_int32_t flags, u_char *str) PUTCHAR(id, outp); esp->es_client.ea_id = id; msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u_int32_t) + - SHA_DIGESTSIZE; + SHA_DIGEST_LENGTH; PUTSHORT(msglen, outp); PUTCHAR(EAPT_SRP, outp); PUTCHAR(EAPSRP_CVALIDATOR, outp); PUTLONG(flags, outp); - BCOPY(str, outp, SHA_DIGESTSIZE); + BCOPY(str, outp, SHA_DIGEST_LENGTH); output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen); } @@ -1547,9 +1564,9 @@ write_pseudonym(eap_state *esp, u_char *inp, int len, int id) { u_char val; u_char *datp, *digp; - SHA1_CTX ctxt; - u_char dig[SHA_DIGESTSIZE]; - int dsize, fd, olen = len; + PPP_MD_CTX *ctxt; + u_char dig[SHA_DIGEST_LENGTH]; + int dsize, fd, olen = len, diglen = sizeof(dig); /* * Do the decoding by working backwards. This eliminates the need @@ -1557,22 +1574,30 @@ write_pseudonym(eap_state *esp, u_char *inp, int len, int id) */ val = id; while (len > 0) { - if ((dsize = len % SHA_DIGESTSIZE) == 0) - dsize = SHA_DIGESTSIZE; + if ((dsize = len % SHA_DIGEST_LENGTH) == 0) + dsize = SHA_DIGEST_LENGTH; len -= dsize; datp = inp + len; - SHA1Init(&ctxt); - SHA1Update(&ctxt, &val, 1); - SHA1Update(&ctxt, esp->es_client.ea_skey, SESSION_KEY_LEN); - if (len > 0) { - SHA1Update(&ctxt, datp, SHA_DIGESTSIZE); - } else { - SHA1Update(&ctxt, esp->es_client.ea_name, - esp->es_client.ea_namelen); + ctxt = PPP_MD_CTX_new(); + if (ctxt) { + + PPP_DigestInit(ctxt, PPP_sha1()); + PPP_DigestUpdate(ctxt, &val, 1); + PPP_DigestUpdate(ctxt, esp->es_client.ea_skey, + SESSION_KEY_LEN); + if (len > 0) { + PPP_DigestUpdate(ctxt, datp, SHA_DIGEST_LENGTH); + } else { + PPP_DigestUpdate(ctxt, esp->es_client.ea_name, + esp->es_client.ea_namelen); + } + PPP_DigestFinal(ctxt, dig, &diglen); + + for (digp = dig; digp < dig + SHA_DIGEST_LENGTH; digp++) + *datp++ ^= *digp; + + PPP_MD_CTX_free(ctxt); } - SHA1Final(dig, &ctxt); - for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++) - *datp++ ^= *digp; } /* Now check that the result is sane */ @@ -1642,8 +1667,9 @@ eap_request(eap_state *esp, u_char *inp, int id, int len) int secret_len; char secret[MAXWORDLEN]; char rhostname[256]; - MD5_CTX mdContext; - u_char hash[MD5_SIGNATURE_SIZE]; + PPP_MD_CTX *mdctx; + u_char hash[MD5_DIGEST_LENGTH]; + int hashlen = MD5_DIGEST_LENGTH; #ifdef PPP_WITH_EAPTLS u_char flags; struct eaptls_session *ets = esp->es_client.ea_session; @@ -1653,8 +1679,9 @@ eap_request(eap_state *esp, u_char *inp, int id, int len) struct t_client *tc; struct t_num sval, gval, Nval, *Ap, Bval; u_char vals[2]; - SHA1_CTX ctxt; - u_char dig[SHA_DIGESTSIZE]; + PPP_MD_CTX *ctxt; + u_char dig[SHA_DIGEST_LENGTH]; + int diglen = sizeof(dig); int fd; #endif /* PPP_WITH_SRP */ @@ -1780,15 +1807,29 @@ eap_request(eap_state *esp, u_char *inp, int id, int len) eap_send_nak(esp, id, EAPT_SRP); break; } - MD5_Init(&mdContext); - typenum = id; - MD5_Update(&mdContext, &typenum, 1); - MD5_Update(&mdContext, (u_char *)secret, secret_len); - BZERO(secret, sizeof (secret)); - MD5_Update(&mdContext, inp, vallen); - MD5_Final(hash, &mdContext); - eap_chap_response(esp, id, hash, esp->es_client.ea_name, - esp->es_client.ea_namelen); + + mdctx = PPP_MD_CTX_new(); + if (mdctx != NULL) { + if (PPP_DigestInit(mdctx, PPP_md5())) { + typenum = id; + if (PPP_DigestUpdate(mdctx, &typenum, 1)) { + if (PPP_DigestUpdate(mdctx, secret, secret_len)) { + BZERO(secret, sizeof(secret)); + if (PPP_DigestUpdate(mdctx, inp, vallen)) { + if (PPP_DigestFinal(mdctx, hash, &hashlen)) { + eap_chap_response(esp, id, hash, esp->es_client.ea_name, + esp->es_client.ea_namelen); + PPP_MD_CTX_free(mdctx); + break; + } + } + } + } + } + PPP_MD_CTX_free(mdctx); + } + dbglog("EAP: Invalid MD5 checksum"); + eap_send_nak(esp, id, EAPT_SRP); break; #ifdef PPP_WITH_EAPTLS @@ -2065,7 +2106,7 @@ eap_request(eap_state *esp, u_char *inp, int id, int len) esp->es_client.ea_id, id); } } else { - len -= sizeof (u_int32_t) + SHA_DIGESTSIZE; + len -= sizeof (u_int32_t) + SHA_DIGEST_LENGTH; if (len < 0 || t_clientverify(tc, inp + sizeof (u_int32_t)) != 0) { error("EAP: SRP server verification " @@ -2075,7 +2116,7 @@ eap_request(eap_state *esp, u_char *inp, int id, int len) GETLONG(esp->es_client.ea_keyflags, inp); /* Save pseudonym if user wants it. */ if (len > 0 && esp->es_usepseudo) { - INCPTR(SHA_DIGESTSIZE, inp); + INCPTR(SHA_DIGEST_LENGTH, inp); write_pseudonym(esp, inp, len, id); } } @@ -2092,17 +2133,24 @@ eap_request(eap_state *esp, u_char *inp, int id, int len) warn("EAP: malformed Lightweight rechallenge"); return; } - SHA1Init(&ctxt); - vals[0] = id; - SHA1Update(&ctxt, vals, 1); - SHA1Update(&ctxt, esp->es_client.ea_skey, - SESSION_KEY_LEN); - SHA1Update(&ctxt, inp, len); - SHA1Update(&ctxt, esp->es_client.ea_name, - esp->es_client.ea_namelen); - SHA1Final(dig, &ctxt); - eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig, - SHA_DIGESTSIZE); + ctxt = PPP_MD_CTX_new(); + if (ctxt) { + + vals[0] = id; + PPP_DigestInit(ctxt, PPP_sha1()); + PPP_DigestUpdate(ctxt, vals, 1); + PPP_DigestUpdate(ctxt, esp->es_client.ea_skey, + SESSION_KEY_LEN); + PPP_DigestUpdate(ctxt, inp, len); + PPP_DigestUpdate(ctxt, esp->es_client.ea_name, + esp->es_client.ea_namelen); + PPP_DigestFinal(ctxt, dig, &diglen); + + PPP_MD_CTX_free(ctxt); + + eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig, + SHA_DIGEST_LENGTH); + } break; default: @@ -2112,7 +2160,7 @@ eap_request(eap_state *esp, u_char *inp, int id, int len) } break; #endif /* PPP_WITH_SRP */ - + #ifdef PPP_WITH_CHAPMS case EAPT_MSCHAPV2: if (len < 4) { @@ -2279,13 +2327,15 @@ eap_response(eap_state *esp, u_char *inp, int id, int len) int secret_len; char secret[MAXSECRETLEN]; char rhostname[256]; - MD5_CTX mdContext; - u_char hash[MD5_SIGNATURE_SIZE]; + PPP_MD_CTX *mdctx; + u_char hash[MD5_DIGEST_LENGTH]; + int hashlen = MD5_DIGEST_LENGTH; #ifdef PPP_WITH_SRP struct t_server *ts; struct t_num A; - SHA1_CTX ctxt; - u_char dig[SHA_DIGESTSIZE]; + PPP_MD_CTX *ctxt; + u_char dig[SHA_DIGEST_LENGTH]; + int diglen = sizeof(dig); #endif /* PPP_WITH_SRP */ #ifdef PPP_WITH_EAPTLS @@ -2517,21 +2567,42 @@ eap_response(eap_state *esp, u_char *inp, int id, int len) eap_send_failure(esp); break; } - MD5_Init(&mdContext); - MD5_Update(&mdContext, &esp->es_server.ea_id, 1); - MD5_Update(&mdContext, (u_char *)secret, secret_len); - BZERO(secret, sizeof (secret)); - MD5_Update(&mdContext, esp->es_challenge, esp->es_challen); - MD5_Final(hash, &mdContext); - if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) { - eap_send_failure(esp); - break; + + mdctx = PPP_MD_CTX_new(); + if (mdctx != NULL) { + + if (PPP_DigestInit(mdctx, PPP_md5())) { + + if (PPP_DigestUpdate(mdctx, &esp->es_server.ea_id, 1)) { + + if (PPP_DigestUpdate(mdctx, &secret, secret_len)) { + + BZERO(secret, sizeof(secret)); + if (PPP_DigestUpdate(mdctx, esp->es_challenge, esp->es_challen)) { + + if (PPP_DigestFinal(mdctx, hash, &hashlen)) { + + if (BCMP(hash, inp, MD5_DIGEST_LENGTH) == 0) { + esp->es_server.ea_type = EAPT_MD5CHAP; + eap_send_success(esp); + eap_figure_next_state(esp, 0); + + if (esp->es_rechallenge != 0) { + TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge); + } + PPP_MD_CTX_free(mdctx); + break; + } + } + } + } + } + } + + PPP_MD_CTX_free(mdctx); } - esp->es_server.ea_type = EAPT_MD5CHAP; - eap_send_success(esp); - eap_figure_next_state(esp, 0); - if (esp->es_rechallenge != 0) - TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge); + + eap_send_failure(esp); break; #ifdef PPP_WITH_CHAPMS @@ -2675,9 +2746,9 @@ eap_response(eap_state *esp, u_char *inp, int id, int len) eap_figure_next_state(esp, 1); break; } - if (len < sizeof (u_int32_t) + SHA_DIGESTSIZE) { + if (len < sizeof (u_int32_t) + SHA_DIGEST_LENGTH) { error("EAP: M1 length %d < %d", len, - sizeof (u_int32_t) + SHA_DIGESTSIZE); + sizeof (u_int32_t) + SHA_DIGEST_LENGTH); eap_figure_next_state(esp, 1); break; } @@ -2714,29 +2785,37 @@ eap_response(eap_state *esp, u_char *inp, int id, int len) info("EAP: unexpected SRP Subtype 4 Response"); return; } - if (len != SHA_DIGESTSIZE) { + if (len != SHA_DIGEST_LENGTH) { error("EAP: bad Lightweight rechallenge " "response"); return; } - SHA1Init(&ctxt); - vallen = id; - SHA1Update(&ctxt, &vallen, 1); - SHA1Update(&ctxt, esp->es_server.ea_skey, - SESSION_KEY_LEN); - SHA1Update(&ctxt, esp->es_challenge, esp->es_challen); - SHA1Update(&ctxt, esp->es_server.ea_peer, - esp->es_server.ea_peerlen); - SHA1Final(dig, &ctxt); - if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) { - error("EAP: failed Lightweight rechallenge"); - eap_send_failure(esp); - break; + ctxt = PPP_MD_CTX_new(); + if (ctxt) { + vallen = id; + + PPP_DigestInit(ctxt, PPP_sha1()); + PPP_DigestUpdate(ctxt, &vallen, 1); + PPP_DigestUpdate(ctxt, esp->es_server.ea_skey, + SESSION_KEY_LEN); + PPP_DigestUpdate(ctxt, esp->es_challenge, esp->es_challen); + PPP_DigestUpdate(ctxt, esp->es_server.ea_peer, + esp->es_server.ea_peerlen); + PPP_DigestFinal(ctxt, dig, &diglen); + + PPP_MD_CTX_free(ctxt); + + if (BCMP(dig, inp, SHA_DIGEST_LENGTH) != 0) { + error("EAP: failed Lightweight rechallenge"); + eap_send_failure(esp); + break; + } + + esp->es_server.ea_state = eapOpen; + if (esp->es_lwrechallenge != 0) + TIMEOUT(srp_lwrechallenge, esp, + esp->es_lwrechallenge); } - esp->es_server.ea_state = eapOpen; - if (esp->es_lwrechallenge != 0) - TIMEOUT(srp_lwrechallenge, esp, - esp->es_lwrechallenge); break; } break; @@ -3129,10 +3208,10 @@ eap_printpkt(u_char *inp, int inlen, if (uval != 0) { printer(arg, " f<%X>", uval); } - if ((vallen = len) > SHA_DIGESTSIZE) - vallen = SHA_DIGESTSIZE; + if ((vallen = len) > SHA_DIGEST_LENGTH) + vallen = SHA_DIGEST_LENGTH; printer(arg, " ", len, inp, - len < SHA_DIGESTSIZE ? "?" : ""); + len < SHA_DIGEST_LENGTH ? "?" : ""); INCPTR(vallen, inp); len -= vallen; if (len > 0) { @@ -3302,7 +3381,7 @@ eap_printpkt(u_char *inp, int inlen, printer(arg, " f<%X>", uval); } printer(arg, " ", len, inp, - len == SHA_DIGESTSIZE ? "" : "?"); + len == SHA_DIGEST_LENGTH ? "" : "?"); INCPTR(len, inp); len = 0; break; @@ -3312,9 +3391,9 @@ eap_printpkt(u_char *inp, int inlen, case EAPSRP_LWRECHALLENGE: printer(arg, " ", len, inp, - len == SHA_DIGESTSIZE ? "" : "?"); - if ((vallen = len) > SHA_DIGESTSIZE) - vallen = SHA_DIGESTSIZE; + len == SHA_DIGEST_LENGTH ? "" : "?"); + if ((vallen = len) > SHA_DIGEST_LENGTH) + vallen = SHA_DIGEST_LENGTH; INCPTR(vallen, inp); len -= vallen; break; diff --git a/pppd/eap.h b/pppd/eap.h index 01697a8..8e363e9 100644 --- a/pppd/eap.h +++ b/pppd/eap.h @@ -94,7 +94,6 @@ extern "C" { #define SRP_PSEUDO_ID "pseudo_" #define SRP_PSEUDO_LEN 7 -#define MD5_SIGNATURE_SIZE 16 #define MIN_CHALLENGE_LENGTH 16 #define MAX_CHALLENGE_LENGTH 24 diff --git a/pppd/main.c b/pppd/main.c index 7e47752..b302c08 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -109,6 +109,7 @@ #include "ccp.h" #include "ecp.h" #include "pathnames.h" +#include "ppp-crypto.h" #ifdef PPP_WITH_TDB #include "tdb.h" @@ -294,6 +295,8 @@ main(int argc, char *argv[]) struct protent *protp; char numbuf[16]; + PPP_crypto_init(); + strlcpy(path_ipup, PPP_PATH_IPUP, MAXPATHLEN); strlcpy(path_ipdown, PPP_PATH_IPDOWN, MAXPATHLEN); @@ -364,6 +367,11 @@ main(int argc, char *argv[]) if (debug) setlogmask(LOG_UPTO(LOG_DEBUG)); + if (show_options) { + showopts(); + die(0); + } + /* * Check that we are running as root. */ @@ -581,6 +589,7 @@ main(int argc, char *argv[]) } } + PPP_crypto_deinit(); die(status); return 0; } diff --git a/pppd/md4.c b/pppd/md4.c deleted file mode 100644 index 88f3413..0000000 --- a/pppd/md4.c +++ /dev/null @@ -1,293 +0,0 @@ -/* -** ******************************************************************** -** md4.c -- Implementation of MD4 Message Digest Algorithm ** -** Updated: 2/16/90 by Ronald L. Rivest ** -** (C) 1990 RSA Data Security, Inc. ** -** ******************************************************************** -*/ - -/* -** To use MD4: -** -- Include md4.h in your program -** -- Declare an MDstruct MD to hold the state of the digest -** computation. -** -- Initialize MD using MDbegin(&MD) -** -- For each full block (64 bytes) X you wish to process, call -** MD4Update(&MD,X,512) -** (512 is the number of bits in a full block.) -** -- For the last block (less than 64 bytes) you wish to process, -** MD4Update(&MD,X,n) -** where n is the number of bits in the partial block. A partial -** block terminates the computation, so every MD computation -** should terminate by processing a partial block, even if it -** has n = 0. -** -- The message digest is available in MD.buffer[0] ... -** MD.buffer[3]. (Least-significant byte of each word -** should be output first.) -** -- You can print out the digest using MDprint(&MD) -*/ - -/* Implementation notes: -** This implementation assumes that ints are 32-bit quantities. -*/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define TRUE 1 -#define FALSE 0 - -/* Compile-time includes -*/ -#include -#include "md4.h" -#include "pppd.h" - -/* Compile-time declarations of MD4 "magic constants". -*/ -#define I0 0x67452301 /* Initial values for MD buffer */ -#define I1 0xefcdab89 -#define I2 0x98badcfe -#define I3 0x10325476 -#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */ -#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */ -/* C2 and C3 are from Knuth, The Art of Programming, Volume 2 -** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley. -** Table 2, page 660. -*/ - -#define fs1 3 /* round 1 shift amounts */ -#define fs2 7 -#define fs3 11 -#define fs4 19 -#define gs1 3 /* round 2 shift amounts */ -#define gs2 5 -#define gs3 9 -#define gs4 13 -#define hs1 3 /* round 3 shift amounts */ -#define hs2 9 -#define hs3 11 -#define hs4 15 - -/* Compile-time macro declarations for MD4. -** Note: The "rot" operator uses the variable "tmp". -** It assumes tmp is declared as unsigned int, so that the >> -** operator will shift in zeros rather than extending the sign bit. -*/ -#define f(X,Y,Z) ((X&Y) | ((~X)&Z)) -#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z)) -#define h(X,Y,Z) (X^Y^Z) -#define rot(X,S) (tmp=X,(tmp<>(32-S))) -#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s) -#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s) -#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s) - -/* MD4print(MDp) -** Print message digest buffer MDp as 32 hexadecimal digits. -** Order is from low-order byte of buffer[0] to high-order byte of -** buffer[3]. -** Each byte is printed with high-order hexadecimal digit first. -** This is a user-callable routine. -*/ -void -MD4Print(MD4_CTX *MDp) -{ - int i,j; - for (i=0;i<4;i++) - for (j=0;j<32;j=j+8) - printf("%02x",(MDp->buffer[i]>>j) & 0xFF); -} - -/* MD4Init(MDp) -** Initialize message digest buffer MDp. -** This is a user-callable routine. -*/ -void -MD4Init(MD4_CTX *MDp) -{ - int i; - MDp->buffer[0] = I0; - MDp->buffer[1] = I1; - MDp->buffer[2] = I2; - MDp->buffer[3] = I3; - for (i=0;i<8;i++) MDp->count[i] = 0; - MDp->done = 0; -} - -/* MDblock(MDp,X) -** Update message digest buffer MDp->buffer using 16-word data block X. -** Assumes all 16 words of X are full of data. -** Does not update MDp->count. -** This routine is not user-callable. -*/ -static void -MDblock(MD4_CTX *MDp, unsigned char *Xb) -{ - register unsigned int tmp, A, B, C, D; - unsigned int X[16]; - int i; - - for (i = 0; i < 16; ++i) { - X[i] = Xb[0] + (Xb[1] << 8) + (Xb[2] << 16) + (Xb[3] << 24); - Xb += 4; - } - - A = MDp->buffer[0]; - B = MDp->buffer[1]; - C = MDp->buffer[2]; - D = MDp->buffer[3]; - /* Update the message digest buffer */ - ff(A , B , C , D , 0 , fs1); /* Round 1 */ - ff(D , A , B , C , 1 , fs2); - ff(C , D , A , B , 2 , fs3); - ff(B , C , D , A , 3 , fs4); - ff(A , B , C , D , 4 , fs1); - ff(D , A , B , C , 5 , fs2); - ff(C , D , A , B , 6 , fs3); - ff(B , C , D , A , 7 , fs4); - ff(A , B , C , D , 8 , fs1); - ff(D , A , B , C , 9 , fs2); - ff(C , D , A , B , 10 , fs3); - ff(B , C , D , A , 11 , fs4); - ff(A , B , C , D , 12 , fs1); - ff(D , A , B , C , 13 , fs2); - ff(C , D , A , B , 14 , fs3); - ff(B , C , D , A , 15 , fs4); - gg(A , B , C , D , 0 , gs1); /* Round 2 */ - gg(D , A , B , C , 4 , gs2); - gg(C , D , A , B , 8 , gs3); - gg(B , C , D , A , 12 , gs4); - gg(A , B , C , D , 1 , gs1); - gg(D , A , B , C , 5 , gs2); - gg(C , D , A , B , 9 , gs3); - gg(B , C , D , A , 13 , gs4); - gg(A , B , C , D , 2 , gs1); - gg(D , A , B , C , 6 , gs2); - gg(C , D , A , B , 10 , gs3); - gg(B , C , D , A , 14 , gs4); - gg(A , B , C , D , 3 , gs1); - gg(D , A , B , C , 7 , gs2); - gg(C , D , A , B , 11 , gs3); - gg(B , C , D , A , 15 , gs4); - hh(A , B , C , D , 0 , hs1); /* Round 3 */ - hh(D , A , B , C , 8 , hs2); - hh(C , D , A , B , 4 , hs3); - hh(B , C , D , A , 12 , hs4); - hh(A , B , C , D , 2 , hs1); - hh(D , A , B , C , 10 , hs2); - hh(C , D , A , B , 6 , hs3); - hh(B , C , D , A , 14 , hs4); - hh(A , B , C , D , 1 , hs1); - hh(D , A , B , C , 9 , hs2); - hh(C , D , A , B , 5 , hs3); - hh(B , C , D , A , 13 , hs4); - hh(A , B , C , D , 3 , hs1); - hh(D , A , B , C , 11 , hs2); - hh(C , D , A , B , 7 , hs3); - hh(B , C , D , A , 15 , hs4); - MDp->buffer[0] += A; - MDp->buffer[1] += B; - MDp->buffer[2] += C; - MDp->buffer[3] += D; -} - -/* MD4Update(MDp,X,count) -** Input: X -- a pointer to an array of unsigned characters. -** count -- the number of bits of X to use. -** (if not a multiple of 8, uses high bits of last byte.) -** Update MDp using the number of bits of X given by count. -** This is the basic input routine for an MD4 user. -** The routine completes the MD computation when count < 512, so -** every MD computation should end with one call to MD4Update with a -** count less than 512. A call with count 0 will be ignored if the -** MD has already been terminated (done != 0), so an extra call with -** count 0 can be given as a "courtesy close" to force termination -** if desired. -*/ -void -MD4Update(MD4_CTX *MDp, unsigned char *X, unsigned int count) -{ - unsigned int i, tmp, bit, byte, mask; - unsigned char XX[64]; - unsigned char *p; - - /* return with no error if this is a courtesy close with count - ** zero and MDp->done is true. - */ - if (count == 0 && MDp->done) return; - /* check to see if MD is already done and report error */ - if (MDp->done) - { printf("\nError: MD4Update MD already done."); return; } - - /* Add count to MDp->count */ - tmp = count; - p = MDp->count; - while (tmp) - { tmp += *p; - *p++ = tmp; - tmp = tmp >> 8; - } - - /* Process data */ - if (count == 512) - { /* Full block of data to handle */ - MDblock(MDp,X); - } - else if (count > 512) /* Check for count too large */ - { - printf("\nError: MD4Update called with illegal count value %d.", - count); - return; - } - else /* partial block -- must be last block so finish up */ - { - /* Find out how many bytes and residual bits there are */ - byte = count >> 3; - bit = count & 7; - /* Copy X into XX since we need to modify it */ - if (count) - for (i=0;i<=byte;i++) XX[i] = X[i]; - for (i=byte+1;i<64;i++) XX[i] = 0; - /* Add padding '1' bit and low-order zeros in last byte */ - mask = 1 << (7 - bit); - XX[byte] = (XX[byte] | mask) & ~( mask - 1); - /* If room for bit count, finish up with this block */ - if (byte <= 55) - { - for (i=0;i<8;i++) XX[56+i] = MDp->count[i]; - MDblock(MDp,XX); - } - else /* need to do two blocks to finish up */ - { - MDblock(MDp,XX); - for (i=0;i<56;i++) XX[i] = 0; - for (i=0;i<8;i++) XX[56+i] = MDp->count[i]; - MDblock(MDp,XX); - } - /* Set flag saying we're done with MD computation */ - MDp->done = 1; - } -} - -/* -** Finish up MD4 computation and return message digest. -*/ -void -MD4Final(unsigned char *buf, MD4_CTX *MD) -{ - int i, j; - unsigned int w; - - MD4Update(MD, NULL, 0); - for (i = 0; i < 4; ++i) { - w = MD->buffer[i]; - for (j = 0; j < 4; ++j) { - *buf++ = w; - w >>= 8; - } - } -} - -/* -** End of md4.c -****************************(cut)***********************************/ diff --git a/pppd/md4.h b/pppd/md4.h deleted file mode 100644 index 546ea02..0000000 --- a/pppd/md4.h +++ /dev/null @@ -1,68 +0,0 @@ - -/* -** ******************************************************************** -** md4.h -- Header file for implementation of ** -** MD4 Message Digest Algorithm ** -** Updated: 2/13/90 by Ronald L. Rivest ** -** (C) 1990 RSA Data Security, Inc. ** -** ******************************************************************** -*/ -#ifndef PPP_MD4_H -#define PPP_MD4_H - -#include "pppdconf.h" - -#ifndef USE_MD4 -#include -#define MD4Init MD4_Init -#define MD4Update MD4_Update -#define MD4Final MD4_Final -#else - -/* MDstruct is the data structure for a message digest computation. -*/ -typedef struct { - unsigned int buffer[4]; /* Holds 4-word result of MD computation */ - unsigned char count[8]; /* Number of bits processed so far */ - unsigned int done; /* Nonzero means MD computation finished */ -} MD4_CTX; - -/* MD4Init(MD4_CTX *) -** Initialize the MD4_CTX prepatory to doing a message digest -** computation. -*/ -extern void MD4Init(MD4_CTX *MD); - -/* MD4Update(MD,X,count) -** Input: X -- a pointer to an array of unsigned characters. -** count -- the number of bits of X to use (an unsigned int). -** Updates MD using the first "count" bits of X. -** The array pointed to by X is not modified. -** If count is not a multiple of 8, MD4Update uses high bits of -** last byte. -** This is the basic input routine for a user. -** The routine terminates the MD computation when count < 512, so -** every MD computation should end with one call to MD4Update with a -** count less than 512. Zero is OK for a count. -*/ -extern void MD4Update(MD4_CTX *MD, unsigned char *X, unsigned int count); - -/* MD4Print(MD) -** Prints message digest buffer MD as 32 hexadecimal digits. -** Order is from low-order byte of buffer[0] to high-order byte -** of buffer[3]. -** Each byte is printed with high-order hexadecimal digit first. -*/ -extern void MD4Print(MD4_CTX *); - -/* MD4Final(buf, MD) -** Returns message digest from MD and terminates the message -** digest computation. -*/ -extern void MD4Final(unsigned char *, MD4_CTX *); - -/* -** End of md4.h -****************************(cut)***********************************/ -#endif /* USE_MD4 */ -#endif /* PPP_MD4_H */ diff --git a/pppd/md5.c b/pppd/md5.c deleted file mode 100644 index 9fb3397..0000000 --- a/pppd/md5.c +++ /dev/null @@ -1,303 +0,0 @@ - - -/* - *********************************************************************** - ** md5.c -- the source code for MD5 routines ** - ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** - ** Created: 2/17/90 RLR ** - ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. ** - *********************************************************************** - */ - -/* - *********************************************************************** - ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** - ** ** - ** License to copy and use this software is granted provided that ** - ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** - ** Digest Algorithm" in all material mentioning or referencing this ** - ** software or this function. ** - ** ** - ** License is also granted to make and use derivative works ** - ** provided that such works are identified as "derived from the RSA ** - ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** - ** material mentioning or referencing the derived work. ** - ** ** - ** RSA Data Security, Inc. makes no representations concerning ** - ** either the merchantability of this software or the suitability ** - ** of this software for any particular purpose. It is provided "as ** - ** is" without express or implied warranty of any kind. ** - ** ** - ** These notices must be retained in any copies of any part of this ** - ** documentation and/or software. ** - *********************************************************************** - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "md5.h" - -/* - *********************************************************************** - ** Message-digest routines: ** - ** To form the message digest for a message M ** - ** (1) Initialize a context buffer mdContext using MD5_Init ** - ** (2) Call MD5_Update on mdContext and M ** - ** (3) Call MD5_Final on mdContext ** - ** The message digest is now in mdContext->digest[0...15] ** - *********************************************************************** - */ - -/* forward declaration */ -static void Transform (UINT4 *buf, UINT4 *in); - -static unsigned char PADDING[64] = { - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* F, G, H and I are basic MD5 functions */ -#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define I(x, y, z) ((y) ^ ((x) | (~z))) - -/* ROTATE_LEFT rotates x left n bits */ -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) - -/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ -/* Rotation is separate from addition to prevent recomputation */ -#define FF(a, b, c, d, x, s, ac) \ - {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define GG(a, b, c, d, x, s, ac) \ - {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define HH(a, b, c, d, x, s, ac) \ - {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define II(a, b, c, d, x, s, ac) \ - {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } - -#ifdef __STDC__ -#define UL(x) x##U -#else -#define UL(x) x -#endif - -/* The routine MD5_Init initializes the message-digest context - mdContext. All fields are set to zero. - */ -void MD5_Init (MD5_CTX *mdContext) -{ - mdContext->i[0] = mdContext->i[1] = (UINT4)0; - - /* Load magic initialization constants. - */ - mdContext->buf[0] = (UINT4)0x67452301; - mdContext->buf[1] = (UINT4)0xefcdab89; - mdContext->buf[2] = (UINT4)0x98badcfe; - mdContext->buf[3] = (UINT4)0x10325476; -} - -/* The routine MD5Update updates the message-digest context to - account for the presence of each of the characters inBuf[0..inLen-1] - in the message whose digest is being computed. - */ -void MD5_Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen) -{ - UINT4 in[16]; - int mdi; - unsigned int i, ii; - - /* compute number of bytes mod 64 */ - mdi = (int)((mdContext->i[0] >> 3) & 0x3F); - - /* update number of bits */ - if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) - mdContext->i[1]++; - mdContext->i[0] += ((UINT4)inLen << 3); - mdContext->i[1] += ((UINT4)inLen >> 29); - - while (inLen--) { - /* add new character to buffer, increment mdi */ - mdContext->in[mdi++] = *inBuf++; - - /* transform if necessary */ - if (mdi == 0x40) { - for (i = 0, ii = 0; i < 16; i++, ii += 4) - in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | - (((UINT4)mdContext->in[ii+2]) << 16) | - (((UINT4)mdContext->in[ii+1]) << 8) | - ((UINT4)mdContext->in[ii]); - Transform (mdContext->buf, in); - mdi = 0; - } - } -} - -/* The routine MD5Final terminates the message-digest computation and - ends with the desired message digest in mdContext->digest[0...15]. - */ -void MD5_Final (unsigned char hash[], MD5_CTX *mdContext) -{ - UINT4 in[16]; - int mdi; - unsigned int i, ii; - unsigned int padLen; - - /* save number of bits */ - in[14] = mdContext->i[0]; - in[15] = mdContext->i[1]; - - /* compute number of bytes mod 64 */ - mdi = (int)((mdContext->i[0] >> 3) & 0x3F); - - /* pad out to 56 mod 64 */ - padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); - MD5_Update (mdContext, PADDING, padLen); - - /* append length in bits and transform */ - for (i = 0, ii = 0; i < 14; i++, ii += 4) - in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | - (((UINT4)mdContext->in[ii+2]) << 16) | - (((UINT4)mdContext->in[ii+1]) << 8) | - ((UINT4)mdContext->in[ii]); - Transform (mdContext->buf, in); - - /* store buffer in digest */ - for (i = 0, ii = 0; i < 4; i++, ii += 4) { - mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); - mdContext->digest[ii+1] = - (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); - mdContext->digest[ii+2] = - (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); - mdContext->digest[ii+3] = - (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); - } - memcpy(hash, mdContext->digest, 16); -} - -/* Basic MD5 step. Transforms buf based on in. - */ -static void Transform (UINT4 *buf, UINT4 *in) -{ - UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; - - /* Round 1 */ -#define S11 7 -#define S12 12 -#define S13 17 -#define S14 22 - FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */ - FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */ - FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */ - FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */ - FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */ - FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */ - FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */ - FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */ - FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */ - FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */ - FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */ - FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */ - FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */ - FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */ - FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */ - FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */ - - /* Round 2 */ -#define S21 5 -#define S22 9 -#define S23 14 -#define S24 20 - GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */ - GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */ - GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */ - GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */ - GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */ - GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */ - GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */ - GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */ - GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */ - GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */ - GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */ - GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */ - GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */ - GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */ - GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */ - GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */ - - /* Round 3 */ -#define S31 4 -#define S32 11 -#define S33 16 -#define S34 23 - HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */ - HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */ - HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */ - HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */ - HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */ - HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */ - HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */ - HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */ - HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */ - HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */ - HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */ - HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */ - HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */ - HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */ - HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */ - HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */ - - /* Round 4 */ -#define S41 6 -#define S42 10 -#define S43 15 -#define S44 21 - II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */ - II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */ - II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */ - II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */ - II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */ - II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */ - II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */ - II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */ - II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */ - II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */ - II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */ - II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */ - II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */ - II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */ - II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */ - II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */ - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -/* - *********************************************************************** - ** End of md5.c ** - ******************************** (cut) ******************************** - */ diff --git a/pppd/md5.h b/pppd/md5.h deleted file mode 100644 index 31f410d..0000000 --- a/pppd/md5.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - *********************************************************************** - ** md5.h -- header file for implementation of MD5 ** - ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** - ** Created: 2/17/90 RLR ** - ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** - ** Revised (for MD5): RLR 4/27/91 ** - ** -- G modified to have y&~z instead of y&z ** - ** -- FF, GG, HH modified to add in last register done ** - ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** - ** -- distinct additive constant for each step ** - ** -- round 4 added, working mod 7 ** - *********************************************************************** - */ - -/* - *********************************************************************** - ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** - ** ** - ** License to copy and use this software is granted provided that ** - ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** - ** Digest Algorithm" in all material mentioning or referencing this ** - ** software or this function. ** - ** ** - ** License is also granted to make and use derivative works ** - ** provided that such works are identified as "derived from the RSA ** - ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** - ** material mentioning or referencing the derived work. ** - ** ** - ** RSA Data Security, Inc. makes no representations concerning ** - ** either the merchantability of this software or the suitability ** - ** of this software for any particular purpose. It is provided "as ** - ** is" without express or implied warranty of any kind. ** - ** ** - ** These notices must be retained in any copies of any part of this ** - ** documentation and/or software. ** - *********************************************************************** - */ -#ifndef PPP_MD5_H -#define PPP_MD5_H - -#include "pppdconf.h" - -#ifndef USE_MD5 -#include -#else - -/* typedef a 32-bit type */ -#ifdef _LP64 -typedef unsigned int UINT4; -typedef int INT4; -#else -typedef unsigned long UINT4; -typedef long INT4; -#endif -#define _UINT4_T - -/* Data structure for MD5 (Message-Digest) computation */ -typedef struct { - UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ - UINT4 buf[4]; /* scratch buffer */ - unsigned char in[64]; /* input buffer */ - unsigned char digest[16]; /* actual digest after MD5Final call */ -} MD5_CTX; - -void MD5_Init (MD5_CTX *mdContext); -void MD5_Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen); -void MD5_Final (unsigned char hash[], MD5_CTX *mdContext); - -#endif /* USE_MD5 */ -#endif /* PPP_MD5_H */ diff --git a/pppd/mppe.c b/pppd/mppe.c index f1b7abf..c1bc4d3 100644 --- a/pppd/mppe.c +++ b/pppd/mppe.c @@ -1,4 +1,4 @@ -/* * mppe.c - MPPE key implementation +/* mppe.c - MPPE key implementation * * Copyright (c) 2020 Eivind Naess. All rights reserved. * Copyright (c) 2008 Paul Mackerras. All rights reserved. @@ -26,7 +26,6 @@ * 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 @@ -38,11 +37,10 @@ #include "pppd.h" #include "fsm.h" -#include "md4.h" -#include "sha1.h" #include "ccp.h" #include "chap_ms.h" #include "mppe.h" +#include "ppp-crypto.h" u_char mppe_send_key[MPPE_MAX_KEY_SIZE]; u_char mppe_recv_key[MPPE_MAX_KEY_SIZE]; @@ -111,16 +109,33 @@ mppe_clear_keys(void) * RFC 2548 (RADIUS support) requires us to export this function (ugh). */ void -mppe_set_chapv1(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE]) +mppe_set_chapv1(unsigned char *rchallenge, unsigned char *PasswordHashHash) { - SHA1_CTX sha1Context; - u_char Digest[SHA1_SIGNATURE_SIZE]; + PPP_MD_CTX *ctx; + u_char Digest[SHA_DIGEST_LENGTH]; + int DigestLen; + + ctx = PPP_MD_CTX_new(); + if (ctx != NULL) { + + if (PPP_DigestInit(ctx, PPP_sha1())) { + + if (PPP_DigestUpdate(ctx, PasswordHashHash, MD4_DIGEST_LENGTH)) { + + if (PPP_DigestUpdate(ctx, PasswordHashHash, MD4_DIGEST_LENGTH)) { + + if (PPP_DigestUpdate(ctx, rchallenge, 8)) { + + DigestLen = SHA_DIGEST_LENGTH; + PPP_DigestFinal(ctx, Digest, &DigestLen); + } + } + } + } + + PPP_MD_CTX_free(ctx); + } - SHA1_Init(&sha1Context); - SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - SHA1_Update(&sha1Context, rchallenge, 8); - SHA1_Final(Digest, &sha1Context); /* Same key in both directions. */ mppe_set_keys(Digest, Digest, sizeof(Digest)); @@ -133,13 +148,15 @@ mppe_set_chapv1(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE]) * NTHashHash from the server. */ void -mppe_set_chapv2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], - u_char NTResponse[MS_AUTH_NTRESP_LEN], int IsServer) +mppe_set_chapv2(unsigned char *PasswordHashHash, unsigned char *NTResponse, + int IsServer) { - SHA1_CTX sha1Context; - u_char MasterKey[SHA1_SIGNATURE_SIZE]; - u_char SendKey[SHA1_SIGNATURE_SIZE]; - u_char RecvKey[SHA1_SIGNATURE_SIZE]; + PPP_MD_CTX *ctx; + + u_char MasterKey[SHA_DIGEST_LENGTH]; + u_char SendKey[SHA_DIGEST_LENGTH]; + u_char RecvKey[SHA_DIGEST_LENGTH]; + int KeyLen; u_char SHApad1[40] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -183,11 +200,26 @@ mppe_set_chapv2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], 0x6b, 0x65, 0x79, 0x2e }; u_char *s; - SHA1_Init(&sha1Context); - SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - SHA1_Update(&sha1Context, NTResponse, 24); - SHA1_Update(&sha1Context, Magic1, sizeof(Magic1)); - SHA1_Final(MasterKey, &sha1Context); + ctx = PPP_MD_CTX_new(); + if (ctx != NULL) { + + if (PPP_DigestInit(ctx, PPP_sha1())) { + + if (PPP_DigestUpdate(ctx, PasswordHashHash, MD4_DIGEST_LENGTH)) { + + if (PPP_DigestUpdate(ctx, NTResponse, 24)) { + + if (PPP_DigestUpdate(ctx, Magic1, sizeof(Magic1))) { + + KeyLen = SHA_DIGEST_LENGTH; + PPP_DigestFinal(ctx, MasterKey, &KeyLen); + } + } + } + } + + PPP_MD_CTX_free(ctx); + } /* * generate send key @@ -196,12 +228,31 @@ mppe_set_chapv2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], s = Magic3; else s = Magic2; - SHA1_Init(&sha1Context); - SHA1_Update(&sha1Context, MasterKey, 16); - SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1)); - SHA1_Update(&sha1Context, s, 84); - SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2)); - SHA1_Final(SendKey, &sha1Context); + + ctx = PPP_MD_CTX_new(); + if (ctx != NULL) { + + if (PPP_DigestInit(ctx, PPP_sha1())) { + + if (PPP_DigestUpdate(ctx, MasterKey, 16)) { + + if (PPP_DigestUpdate(ctx, SHApad1, sizeof(SHApad1))) { + + if (PPP_DigestUpdate(ctx, s, 84)) { + + if (PPP_DigestUpdate(ctx, SHApad2, sizeof(SHApad2))) { + + KeyLen = SHA_DIGEST_LENGTH; + PPP_DigestFinal(ctx, SendKey, &KeyLen); + } + } + } + } + } + + PPP_MD_CTX_free(ctx); + } + /* * generate recv key @@ -210,14 +261,32 @@ mppe_set_chapv2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], s = Magic2; else s = Magic3; - SHA1_Init(&sha1Context); - SHA1_Update(&sha1Context, MasterKey, 16); - SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1)); - SHA1_Update(&sha1Context, s, 84); - SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2)); - SHA1_Final(RecvKey, &sha1Context); - - mppe_set_keys(SendKey, RecvKey, SHA1_SIGNATURE_SIZE); + + ctx = PPP_MD_CTX_new(); + if (ctx != NULL) { + + if (PPP_DigestInit(ctx, PPP_sha1())) { + + if (PPP_DigestUpdate(ctx, MasterKey, 16)) { + + if (PPP_DigestUpdate(ctx, SHApad1, sizeof(SHApad1))) { + + if (PPP_DigestUpdate(ctx, s, 84)) { + + if (PPP_DigestUpdate(ctx, SHApad2, sizeof(SHApad2))) { + + KeyLen = SHA_DIGEST_LENGTH; + PPP_DigestFinal(ctx, RecvKey, &KeyLen); + } + } + } + } + } + + PPP_MD_CTX_free(ctx); + } + + mppe_set_keys(SendKey, RecvKey, SHA_DIGEST_LENGTH); } #ifndef UNIT_TEST diff --git a/pppd/mppe.h b/pppd/mppe.h index ade208f..f1c53c3 100644 --- a/pppd/mppe.h +++ b/pppd/mppe.h @@ -179,13 +179,13 @@ bool mppe_keys_isset(void); /* * Set mppe_xxxx_key from NT Password Hash Hash (MSCHAPv1), see RFC3079 */ -void mppe_set_chapv1(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE]); +void mppe_set_chapv1(unsigned char *rchallenge, unsigned char *PasswordHashHash); /* * Set the mppe_xxxx_key from MS-CHAP-v2 credentials, see RFC3079 */ -void mppe_set_chapv2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], - u_char NTResponse[MS_AUTH_NTRESP_LEN], int IsServer); +void mppe_set_chapv2(unsigned char *PasswordHashHash, + unsigned char *NTResponse, int IsServer); #endif // #ifdef PPP_WITH_MPPE #endif // #ifdef PPP_MPPE_H diff --git a/pppd/options.c b/pppd/options.c index 92997e6..cea09e3 100644 --- a/pppd/options.c +++ b/pppd/options.c @@ -127,6 +127,7 @@ char req_ifname[IFNAMSIZ]; /* requested interface name */ bool multilink = 0; /* Enable multilink operation */ char *bundle_name = NULL; /* bundle name for multilink */ bool dump_options; /* print out option values */ +bool show_options; /* print all supported options and exit */ bool dryrun; /* print out option values and exit */ char *domain; /* domain name set by domain option */ int child_wait = 5; /* # seconds to wait for children at exit */ @@ -263,6 +264,10 @@ option_t general_options[] = { { "--version", o_special_noarg, (void *)showversion, "Show version number" }, + { "-v", o_special_noarg, (void *)showversion, + "Show version number" }, + { "show-options", o_bool, &show_options, + "Show all options and exit", 1 }, { "--help", o_special_noarg, (void *)showhelp, "Show brief listing of options" }, { "-h", o_special_noarg, (void *)showhelp, @@ -390,23 +395,6 @@ option_t general_options[] = { #define IMPLEMENTATION "" #endif -static char *usage_string = "\ -pppd version %s\n\ -Usage: %s [ options ], where options are:\n\ - Communicate over the named device\n\ - Set the baud rate to \n\ - : Set the local and/or remote interface IP\n\ - addresses. Either one may be omitted.\n\ - asyncmap Set the desired async map to hex \n\ - auth Require authentication from peer\n\ - connect

Invoke shell command

to set up the serial line\n\ - crtscts Use hardware RTS/CTS flow control\n\ - defaultroute Add default route through interface\n\ - file Take options from file \n\ - modem Use modem control lines\n\ - mru Set MRU value to for negotiation\n\ -See pppd(8) for more options.\n\ -"; /* * parse_args - parse a string of arguments from the command line. @@ -1066,8 +1054,33 @@ print_options(printer_func printer, void *arg) static void usage(void) { - if (phase == PHASE_INITIALIZE) - fprintf(stderr, usage_string, VERSION, progname); + FILE *fp = stderr; + if (phase == PHASE_INITIALIZE) { + fprintf(fp, "%s v%s\n", PACKAGE_NAME, PACKAGE_VERSION); + fprintf(fp, "Copyright (C) 1999-2022 Paul Mackerras, and others. All rights reserved.\n\n"); + + + fprintf(fp, "License BSD: The 3 clause BSD license \n"); + fprintf(fp, "This is free software: you are free to change and redistribute it.\n"); + fprintf(fp, "There is NO WARRANTY, to the extent permitted by law.\n\n"); + + fprintf(fp, "Report Bugs:\n %s\n\n", PACKAGE_BUGREPORT); + fprintf(fp, "Usage: %s [ options ], where options are:\n", progname); + fprintf(fp, " Communicate over the named device\n"); + fprintf(fp, " Set the baud rate to \n"); + fprintf(fp, " : Set the local and/or remote interface IP\n"); + fprintf(fp, " addresses. Either one may be omitted.\n"); + fprintf(fp, " asyncmap Set the desired async map to hex \n"); + fprintf(fp, " auth Require authentication from peer\n"); + fprintf(fp, " connect

Invoke shell command

to set up the serial line\n"); + fprintf(fp, " crtscts Use hardware RTS/CTS flow control\n"); + fprintf(fp, " defaultroute Add default route through interface\n"); + fprintf(fp, " file Take options from file \n"); + fprintf(fp, " modem Use modem control lines\n"); + fprintf(fp, " mru Set MRU value to for negotiation\n"); + fprintf(fp, " show-options Display an extended list of options\n"); + fprintf(fp, "See pppd(8) for more options.\n"); + } } /* @@ -1096,6 +1109,61 @@ showversion(char **argv) return 0; } +/* + * Print a set of options including the name of the group of options + */ +static void +showopts_list(FILE *fp, const char *title, option_t *list, ...) +{ + option_t *opt = list; + va_list varg; + + if (opt && opt->name) { + va_start(varg, list); + vfprintf(fp, title, varg); + fprintf(fp, ":\n"); + va_end(varg); + + do { + fprintf(fp, " %-22s %s\n", opt->name, opt->description?:""); + opt++; + } while (opt && opt->name); + + fprintf(fp, "\n"); + } +} + +/* + * Dumps the list of available options + */ +void +showopts(void) +{ + struct option_list *list; + FILE *fp = stderr; + int i = 0; + + showopts_list(fp, "General Options", + general_options); + + showopts_list(fp, "Authentication Options", + auth_options); + + for (list = extra_options; list != NULL; list = list->next) + showopts_list(fp, "Extra Options", list->options); + + showopts_list(fp, "Channel Options", + the_channel->options); + + for (i = 0; protocols[i] != NULL; ++i) { + if (protocols[i]->options != NULL) { + showopts_list(fp, "%s Options", + protocols[i]->options, + protocols[i]->name); + } + } +} + /* * option_error - print a message about an error in an option. * The message is logged, and also sent to diff --git a/pppd/plugins/radius/Makefile.am b/pppd/plugins/radius/Makefile.am index 40f4d16..3897e98 100644 --- a/pppd/plugins/radius/Makefile.am +++ b/pppd/plugins/radius/Makefile.am @@ -32,9 +32,6 @@ radius_la_CPPFLAGS = $(RADIUS_CPPFLAGS) radius_la_LDFLAGS = $(RADIUS_LDFLAGS) radius_la_SOURCES = radius.c radius_la_LIBADD = libradiusclient.la -if WITH_OPENSSL -radius_la_LIBADD += $(OPENSSL_LIBS) -endif radattr_la_CPPFLAGS = $(RADIUS_CPPFLAGS) radattr_la_LDFLAGS = $(RADIUS_LDFLAGS) @@ -46,19 +43,9 @@ radrealms_la_SOURCES = radrealms.c libradiusclient_la_SOURCES = \ avpair.c buildreq.c config.c dict.c ip_util.c \ - clientid.c sendserver.c lock.c util.c + clientid.c sendserver.c lock.c util.c md5.c libradiusclient_la_CPPFLAGS = $(RADIUS_CPPFLAGS) -DSYSCONFDIR=\"${sysconfdir}\" -if !WITH_OPENSSL -libradiusclient_la_SOURCES += md5.c -else -if OPENSSL_HAVE_MD5 -libradiusclient_la_SOURCES += md5.c -else -libradiusclient_la_CPPFLAGS += $(OPENSSL_INCLUDES) -endif -endif - EXTRA_DIST = \ $(EXTRA_FILES) \ $(EXTRA_ETC) diff --git a/pppd/plugins/radius/md5.c b/pppd/plugins/radius/md5.c index 8acfb38..5a3903d 100644 --- a/pppd/plugins/radius/md5.c +++ b/pppd/plugins/radius/md5.c @@ -1,13 +1,30 @@ /* * $Id: md5.c,v 1.1 2004/11/14 07:26:26 paulus Exp $ */ -#include +#include -void rc_md5_calc (unsigned char *output, unsigned char *input, unsigned int inlen) +#include + +int rc_md5_calc(unsigned char *out, const unsigned char *in, unsigned int inl) { - MD5_CTX context; + int retval = 0; + int outl = MD5_DIGEST_LENGTH; + + PPP_MD_CTX *ctx = PPP_MD_CTX_new(); + if (ctx) { + + if (PPP_DigestInit(ctx, PPP_md5())) { + + if (PPP_DigestUpdate(ctx, in, inl)) { + + if (PPP_DigestFinal(ctx, out, &outl)) { + + retval = 1; + } + } + } - MD5_Init (&context); - MD5_Update (&context, input, inlen); - MD5_Final (output, &context); + PPP_MD_CTX_free(ctx); + } + return retval; } diff --git a/pppd/plugins/radius/radius.c b/pppd/plugins/radius/radius.c index 02875b4..999a306 100644 --- a/pppd/plugins/radius/radius.c +++ b/pppd/plugins/radius/radius.c @@ -40,7 +40,7 @@ static char const RCSID[] = #include #ifdef PPP_WITH_MPPE #include -#include +#include #endif #endif #include @@ -50,8 +50,6 @@ static char const RCSID[] = #define BUF_LEN 1024 -#define MD5_HASH_SIZE 16 - #define MSDNS 1 static char *config_file = NULL; @@ -400,15 +398,15 @@ radius_chap_verify(char *user, char *ourname, int id, switch (digest->code) { case CHAP_MD5: /* CHAP-Challenge and CHAP-Password */ - if (response_len != MD5_HASH_SIZE) + if (response_len != MD5_DIGEST_LENGTH) return 0; cpassword[0] = id; - memcpy(&cpassword[1], response, MD5_HASH_SIZE); + memcpy(&cpassword[1], response, MD5_DIGEST_LENGTH); rc_avpair_add(&send, PW_CHAP_CHALLENGE, challenge, challenge_len, VENDOR_NONE); rc_avpair_add(&send, PW_CHAP_PASSWORD, - cpassword, MD5_HASH_SIZE + 1, VENDOR_NONE); + cpassword, MD5_DIGEST_LENGTH + 1, VENDOR_NONE); break; #ifdef PPP_WITH_CHAPMS @@ -772,9 +770,12 @@ radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info, unsigned char *challenge) { int i; - MD5_CTX Context; - u_char plain[32]; - u_char buf[16]; + int status = 0; + PPP_MD_CTX *ctx; + unsigned char plain[32]; + unsigned char buf[MD5_DIGEST_LENGTH]; + unsigned int buflen; + if (vp->lvalue != 32) { error("RADIUS: Incorrect attribute length (%d) for MS-CHAP-MPPE-Keys", @@ -784,30 +785,70 @@ radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info, memcpy(plain, vp->strvalue, sizeof(plain)); - MD5_Init(&Context); - MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); - MD5_Update(&Context, req_info->request_vector, AUTH_VECTOR_LEN); - MD5_Final(buf, &Context); + ctx = PPP_MD_CTX_new(); + if (ctx) { - for (i = 0; i < 16; i++) - plain[i] ^= buf[i]; + if (PPP_DigestInit(ctx, PPP_md5())) { - MD5_Init(&Context); - MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); - MD5_Update(&Context, vp->strvalue, 16); - MD5_Final(buf, &Context); + if (PPP_DigestUpdate(ctx, req_info->secret, strlen(req_info->secret))) { - for(i = 0; i < 16; i++) - plain[i + 16] ^= buf[i]; + if (PPP_DigestUpdate(ctx, req_info->request_vector, AUTH_VECTOR_LEN)) { - /* - * Annoying. The "key" returned is just the NTPasswordHashHash, which - * the NAS (us) doesn't need; we only need the start key. So we have - * to generate the start key, sigh. NB: We do not support the LM-Key. - */ - mppe_set_chapv1(challenge, &plain[8]); + buflen = sizeof(buf); + if (PPP_DigestFinal(ctx, buf, &buflen)) { + + status = 1; + } + } + } + } + PPP_MD_CTX_free(ctx); + } + + if (status) { + + for (i = 0; i < MD5_DIGEST_LENGTH; i++) { + plain[i] ^= buf[i]; + } + + status = 0; + ctx = PPP_MD_CTX_new(); + if (ctx) { + + if (PPP_DigestInit(ctx, PPP_md5())) { - return 0; + if (PPP_DigestUpdate(ctx, req_info->secret, strlen(req_info->secret))) { + + if (PPP_DigestUpdate(ctx, vp->strvalue, 16)) { + + buflen = MD5_DIGEST_LENGTH; + if (PPP_DigestFinal(ctx, buf, &buflen)) { + + status = 1; + } + } + } + } + PPP_MD_CTX_free(ctx); + } + + if (status) { + + for(i = 0; i < MD5_DIGEST_LENGTH; i++) { + plain[i + 16] ^= buf[i]; + } + + /* + * Annoying. The "key" returned is just the NTPasswordHashHash, which + * the NAS (us) doesn't need; we only need the start key. So we have + * to generate the start key, sigh. NB: We do not support the LM-Key. + */ + mppe_set_chapv1(challenge, &plain[8]); + return 0; + } + } + + return -1; } /********************************************************************** @@ -825,11 +866,13 @@ static int radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info) { int i; - MD5_CTX Context; - u_char *salt = vp->strvalue; - u_char *crypt = vp->strvalue + 2; - u_char plain[32]; - u_char buf[MD5_HASH_SIZE]; + int status = 0; + PPP_MD_CTX *ctx; + unsigned char *salt = vp->strvalue; + unsigned char *crypt = vp->strvalue + 2; + unsigned char plain[32]; + unsigned char buf[MD5_DIGEST_LENGTH]; + unsigned int buflen; char *type = "Send"; if (vp->attribute == PW_MS_MPPE_RECV_KEY) @@ -848,34 +891,81 @@ radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info) memcpy(plain, crypt, 32); - MD5_Init(&Context); - MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); - MD5_Update(&Context, req_info->request_vector, AUTH_VECTOR_LEN); - MD5_Update(&Context, salt, 2); - MD5_Final(buf, &Context); + ctx = PPP_MD_CTX_new(); + if (ctx) { - for (i = 0; i < 16; i++) - plain[i] ^= buf[i]; + if (PPP_DigestInit(ctx, PPP_md5())) { - if (plain[0] != 16) { - error("RADIUS: Incorrect key length (%d) for MS-MPPE-%s-Key attribute", - (int) plain[0], type); - return -1; + if (PPP_DigestUpdate(ctx, req_info->secret, strlen(req_info->secret))) { + + if (PPP_DigestUpdate(ctx, req_info->request_vector, AUTH_VECTOR_LEN)) { + + if (PPP_DigestUpdate(ctx, salt, 2)) { + + buflen = sizeof(buf); + if (PPP_DigestFinal(ctx, buf, &buflen)) { + + status = 1; + } + } + } + } + } + + PPP_MD_CTX_free(ctx); } - MD5_Init(&Context); - MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); - MD5_Update(&Context, crypt, 16); - MD5_Final(buf, &Context); + if (status) { - plain[16] ^= buf[0]; /* only need the first byte */ + for (i = 0; i < 16; i++) { + plain[i] ^= buf[i]; + } - if (vp->attribute == PW_MS_MPPE_SEND_KEY) - mppe_set_keys(plain + 1, NULL, 16); - else - mppe_set_keys(NULL, plain + 1, 16); + if (plain[0] != 16) { + error("RADIUS: Incorrect key length (%d) for MS-MPPE-%s-Key attribute", + (int) plain[0], type); + return -1; + } - return 0; + status = 0; + ctx = PPP_MD_CTX_new(); + if (ctx) { + + if (PPP_DigestInit(ctx, PPP_md5())) { + + if (PPP_DigestUpdate(ctx, req_info->secret, strlen(req_info->secret))) { + + if (PPP_DigestUpdate(ctx, crypt, 16)) { + + if (PPP_DigestUpdate(ctx, salt, 2)) { + + buflen = sizeof(buf); + if (PPP_DigestFinal(ctx, buf, &buflen)) { + + status = 1; + } + } + } + } + } + + PPP_MD_CTX_free(ctx); + } + + if (status) { + + plain[16] ^= buf[0]; /* only need the first byte */ + + if (vp->attribute == PW_MS_MPPE_SEND_KEY) { + mppe_set_keys(plain + 1, NULL, 16); + } else { + mppe_set_keys(NULL, plain + 1, 16); + } + return 0; + } + } + + return -1; } #endif /* PPP_WITH_MPPE */ diff --git a/pppd/plugins/radius/radiusclient.h b/pppd/plugins/radius/radiusclient.h index 96449be..777e120 100644 --- a/pppd/plugins/radius/radiusclient.h +++ b/pppd/plugins/radius/radiusclient.h @@ -468,6 +468,6 @@ void rc_mdelay(int); /* md5.c */ -void rc_md5_calc(unsigned char *, unsigned char *, unsigned int); +int rc_md5_calc(unsigned char *out, const unsigned char *in, unsigned int inl); #endif /* RADIUSCLIENT_H */ diff --git a/pppd/plugins/winbind.c b/pppd/plugins/winbind.c index 71c0d03..1843d6c 100644 --- a/pppd/plugins/winbind.c +++ b/pppd/plugins/winbind.c @@ -52,6 +52,7 @@ #include #include #include +#include #define BUF_LEN 1024 @@ -556,7 +557,7 @@ winbind_chap_verify(char *user, char *ourname, int id, u_char *lm_response = NULL; int nt_response_size = 0; int lm_response_size = 0; - u_char session_key[16]; + u_char session_key[MD4_DIGEST_LENGTH]; if (response_len != MS_CHAP_RESPONSE_LEN) break; /* not even the right length */ @@ -608,7 +609,7 @@ winbind_chap_verify(char *user, char *ourname, int id, case CHAP_MICROSOFT_V2: { u_char Challenge[8]; - u_char session_key[MD4_SIGNATURE_SIZE]; + u_char session_key[MD4_DIGEST_LENGTH]; char *error_string = NULL; if (response_len != MS_CHAP2_RESPONSE_LEN) diff --git a/pppd/ppp-crypto-priv.h b/pppd/ppp-crypto-priv.h new file mode 100644 index 0000000..984f08a --- /dev/null +++ b/pppd/ppp-crypto-priv.h @@ -0,0 +1,69 @@ +/* ppp-crypo-priv.h - Crypto private data structures + * + * 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. + */ +#ifndef PPP_CRYPTO_PRIV_H +#define PPP_CRYPTO_PRIV_H + +#include "ppp-crypto.h" + +#define MAX_KEY_SIZE 32 +#define MAX_IV_SIZE 32 + +struct _PPP_MD +{ + int (*init_fn)(PPP_MD_CTX *ctx); + int (*update_fn)(PPP_MD_CTX *ctx, const void *data, size_t cnt); + int (*final_fn)(PPP_MD_CTX *ctx, unsigned char *out, unsigned int *outlen); + void (*clean_fn)(PPP_MD_CTX *ctx); +}; + +struct _PPP_MD_CTX +{ + PPP_MD md; + void *priv; +}; + +struct _PPP_CIPHER +{ + int (*init_fn)(PPP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv); + int (*update_fn)(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl); + int (*final_fn)(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl); + void (*clean_fn)(PPP_CIPHER_CTX *ctx); +}; + +struct _PPP_CIPHER_CTX +{ + PPP_CIPHER cipher; + unsigned char key[MAX_KEY_SIZE]; + unsigned char iv[MAX_IV_SIZE]; + int is_encr; + void *priv; +}; + + +#endif diff --git a/pppd/ppp-crypto.c b/pppd/ppp-crypto.c new file mode 100644 index 0000000..ca74327 --- /dev/null +++ b/pppd/ppp-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 +#include + +#include "ppp-crypto.h" +#include "ppp-crypto-priv.h" + +#ifdef PPP_WITH_OPENSSL +#include +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +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 + +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 diff --git a/pppd/ppp-crypto.h b/pppd/ppp-crypto.h new file mode 100644 index 0000000..cb9da86 --- /dev/null +++ b/pppd/ppp-crypto.h @@ -0,0 +1,100 @@ +/* ppp-crypto.h - 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. + */ + +#ifndef PPP_CRYPTO_H +#define PPP_CRYPTO_H + +#ifndef MD5_DIGEST_LENGTH +#define MD5_DIGEST_LENGTH 16 +#endif + +#ifndef MD4_DIGEST_LENGTH +#define MD4_DIGEST_LENGTH 16 +#endif + +#ifndef SHA_DIGEST_LENGTH +#define SHA_DIGEST_LENGTH 20 +#endif + +struct _PPP_MD_CTX; +struct _PPP_MD; + +typedef struct _PPP_MD_CTX PPP_MD_CTX; +typedef struct _PPP_MD PPP_MD; + + +PPP_MD_CTX *PPP_MD_CTX_new(); +void PPP_MD_CTX_free(PPP_MD_CTX*); + + +const PPP_MD *PPP_md4(void); +const PPP_MD *PPP_md5(void); +const PPP_MD *PPP_sha1(void); + + +int PPP_DigestInit(PPP_MD_CTX *ctx, + const PPP_MD *type); +int PPP_DigestUpdate(PPP_MD_CTX *ctx, + const void *data, size_t cnt); +int PPP_DigestFinal(PPP_MD_CTX *ctx, + unsigned char *out, unsigned int *outlen); + + +struct _PPP_CIPHER_CTX; +struct _PPP_CIPHER; + +typedef struct _PPP_CIPHER_CTX PPP_CIPHER_CTX; +typedef struct _PPP_CIPHER PPP_CIPHER; + + +PPP_CIPHER_CTX *PPP_CIPHER_CTX_new(void); +void PPP_CIPHER_CTX_free(PPP_CIPHER_CTX *ctx); + +const PPP_CIPHER *PPP_des_ecb(void); + +void PPP_CIPHER_CTX_set_cipher_data(PPP_CIPHER_CTX *ctx, + const unsigned char *key); + +int PPP_CipherInit(PPP_CIPHER_CTX *ctx, + const PPP_CIPHER *cipher, + const unsigned char *key, + const unsigned char *iv, + int encr); + +int PPP_CipherUpdate(PPP_CIPHER_CTX *ctx, + unsigned char *out, int *outl, + const unsigned char *in, int inl); + +int PPP_CipherFinal(PPP_CIPHER_CTX *ctx, + unsigned char *out, int *outl); + +int PPP_crypto_init(); +int PPP_crypto_deinit(); + +#endif diff --git a/pppd/ppp-des.c b/pppd/ppp-des.c new file mode 100644 index 0000000..695caa4 --- /dev/null +++ b/pppd/ppp-des.c @@ -0,0 +1,730 @@ +/* + * ppp-des.c - PPP/DES implementation for MS-CHAP and EAP SRP-SHA1 + * + * Extracted from chap_ms.c by James Carlson. + * Added abstraction via PPP_Digest* callbacks by Eivind Næss + * + * Copyright (c) 1995 Eric Rosenquist. All rights reserved. + * Copyright (c) 2022 Eivind Næss. All rights reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. 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. + * + * Sections of this code holds different copyright information. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "ppp-crypto-priv.h" + +#ifdef OPENSSL_HAVE_DES + +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define EVP_CIPHER_CTX_reset EVP_CIPHER_CTX_cleanup +#endif + +static int des_init(PPP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv) +{ + if (ctx) { + EVP_CIPHER_CTX *cc = EVP_CIPHER_CTX_new(); + if (cc) { + + if (key) { + memcpy(ctx->key, key, 8); + } + if (iv) { + memcpy(ctx->iv, iv, 8); + } + + if (EVP_CipherInit(cc, EVP_des_ecb(), ctx->key, ctx->iv, ctx->is_encr)) { + + if (EVP_CIPHER_CTX_set_padding(cc, 0)) { + ctx->priv = cc; + return 1; + } + } + + EVP_CIPHER_CTX_free(cc); + } + } + return 0; +} + +static int des_update(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl) +{ + if (ctx) { + return EVP_CipherUpdate((EVP_CIPHER_CTX*) ctx->priv, out, outl, in, inl); + } + return 0; +} + +static int des_final(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ + if (ctx) { + return EVP_CipherFinal((EVP_CIPHER_CTX*) ctx->priv, out, outl); + } + return 0; +} + +static void des_clean(PPP_CIPHER_CTX *ctx) +{ + if (ctx->priv) { + EVP_CIPHER_CTX_free((EVP_CIPHER_CTX*) ctx->priv); + ctx->priv = NULL; + } +} + +#else + +/* + * DES related functions are imported from openssl 3.0 project with the + * follwoing license: + * + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +typedef unsigned int DES_LONG; +typedef unsigned char DES_cblock[8]; +typedef struct DES_ks { + union { + DES_cblock cblock; + /* + * make sure things are correct size on machines with 8 byte longs + */ + DES_LONG deslong[2]; + } ks[16]; +} DES_key_schedule; + + +#define c2l(c,l) (l =((DES_LONG)(*((c)++))) , \ + l|=((DES_LONG)(*((c)++)))<< 8L, \ + l|=((DES_LONG)(*((c)++)))<<16L, \ + l|=((DES_LONG)(*((c)++)))<<24L) + +# define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24L)&0xff)) + +#define ITERATIONS 16 + +#define ROTATE(a,n) (((a)>>(n))+((a)<<(32-(n)))) + +# define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ + (b)^=(t),\ + (a)^=((t)<<(n))) + +#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ + (a)=(a)^(t)^(t>>(16-(n)))) + +# define IP(l,r) \ + { \ + register DES_LONG tt; \ + PERM_OP(r,l,tt, 4,0x0f0f0f0fL); \ + PERM_OP(l,r,tt,16,0x0000ffffL); \ + PERM_OP(r,l,tt, 2,0x33333333L); \ + PERM_OP(l,r,tt, 8,0x00ff00ffL); \ + PERM_OP(r,l,tt, 1,0x55555555L); \ + } + +# define FP(l,r) \ + { \ + register DES_LONG tt; \ + PERM_OP(l,r,tt, 1,0x55555555L); \ + PERM_OP(r,l,tt, 8,0x00ff00ffL); \ + PERM_OP(l,r,tt, 2,0x33333333L); \ + PERM_OP(r,l,tt,16,0x0000ffffL); \ + PERM_OP(l,r,tt, 4,0x0f0f0f0fL); \ + } + +#define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g) +#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ + u=R^s[S ]; \ + t=R^s[S+1] + +#define D_ENCRYPT(LL,R,S) { \ + LOAD_DATA_tmp(R,S,u,t,E0,E1); \ + t=ROTATE(t,4); \ + LL^= \ + DES_SPtrans[0][(u>> 2L)&0x3f]^ \ + DES_SPtrans[2][(u>>10L)&0x3f]^ \ + DES_SPtrans[4][(u>>18L)&0x3f]^ \ + DES_SPtrans[6][(u>>26L)&0x3f]^ \ + DES_SPtrans[1][(t>> 2L)&0x3f]^ \ + DES_SPtrans[3][(t>>10L)&0x3f]^ \ + DES_SPtrans[5][(t>>18L)&0x3f]^ \ + DES_SPtrans[7][(t>>26L)&0x3f]; } + + +static const DES_LONG DES_SPtrans[8][64] = { + { + /* nibble 0 */ + 0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L, + 0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L, + 0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L, + 0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L, + 0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L, + 0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L, + 0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L, + 0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L, + 0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L, + 0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L, + 0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L, + 0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L, + 0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L, + 0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L, + 0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L, + 0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L, + }, + { + /* nibble 1 */ + 0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L, + 0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L, + 0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L, + 0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L, + 0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L, + 0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L, + 0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L, + 0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L, + 0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L, + 0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L, + 0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L, + 0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L, + 0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L, + 0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L, + 0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L, + 0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L, + }, + { + /* nibble 2 */ + 0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L, + 0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L, + 0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L, + 0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L, + 0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L, + 0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L, + 0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L, + 0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L, + 0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L, + 0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L, + 0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L, + 0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L, + 0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L, + 0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L, + 0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L, + 0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L, + }, + { + /* nibble 3 */ + 0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L, + 0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L, + 0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L, + 0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L, + 0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L, + 0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L, + 0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L, + 0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L, + 0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L, + 0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L, + 0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L, + 0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L, + 0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L, + 0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L, + 0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L, + 0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L, + }, + { + /* nibble 4 */ + 0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L, + 0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L, + 0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L, + 0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L, + 0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L, + 0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L, + 0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L, + 0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L, + 0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L, + 0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L, + 0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L, + 0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L, + 0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L, + 0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L, + 0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L, + 0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L, + }, + { + /* nibble 5 */ + 0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L, + 0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L, + 0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L, + 0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L, + 0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L, + 0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L, + 0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L, + 0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L, + 0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L, + 0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L, + 0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L, + 0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L, + 0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L, + 0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L, + 0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L, + 0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L, + }, + { + /* nibble 6 */ + 0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L, + 0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L, + 0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L, + 0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L, + 0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L, + 0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L, + 0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L, + 0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L, + 0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L, + 0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L, + 0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L, + 0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L, + 0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L, + 0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L, + 0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L, + 0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L, + }, + { + /* nibble 7 */ + 0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L, + 0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L, + 0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L, + 0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L, + 0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L, + 0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L, + 0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L, + 0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L, + 0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L, + 0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L, + 0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L, + 0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L, + 0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L, + 0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L, + 0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L, + 0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L, + } +}; + +static const DES_LONG des_skb[8][64] = { + { + /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + 0x00000000L, 0x00000010L, 0x20000000L, 0x20000010L, + 0x00010000L, 0x00010010L, 0x20010000L, 0x20010010L, + 0x00000800L, 0x00000810L, 0x20000800L, 0x20000810L, + 0x00010800L, 0x00010810L, 0x20010800L, 0x20010810L, + 0x00000020L, 0x00000030L, 0x20000020L, 0x20000030L, + 0x00010020L, 0x00010030L, 0x20010020L, 0x20010030L, + 0x00000820L, 0x00000830L, 0x20000820L, 0x20000830L, + 0x00010820L, 0x00010830L, 0x20010820L, 0x20010830L, + 0x00080000L, 0x00080010L, 0x20080000L, 0x20080010L, + 0x00090000L, 0x00090010L, 0x20090000L, 0x20090010L, + 0x00080800L, 0x00080810L, 0x20080800L, 0x20080810L, + 0x00090800L, 0x00090810L, 0x20090800L, 0x20090810L, + 0x00080020L, 0x00080030L, 0x20080020L, 0x20080030L, + 0x00090020L, 0x00090030L, 0x20090020L, 0x20090030L, + 0x00080820L, 0x00080830L, 0x20080820L, 0x20080830L, + 0x00090820L, 0x00090830L, 0x20090820L, 0x20090830L, + }, + { + /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ + 0x00000000L, 0x02000000L, 0x00002000L, 0x02002000L, + 0x00200000L, 0x02200000L, 0x00202000L, 0x02202000L, + 0x00000004L, 0x02000004L, 0x00002004L, 0x02002004L, + 0x00200004L, 0x02200004L, 0x00202004L, 0x02202004L, + 0x00000400L, 0x02000400L, 0x00002400L, 0x02002400L, + 0x00200400L, 0x02200400L, 0x00202400L, 0x02202400L, + 0x00000404L, 0x02000404L, 0x00002404L, 0x02002404L, + 0x00200404L, 0x02200404L, 0x00202404L, 0x02202404L, + 0x10000000L, 0x12000000L, 0x10002000L, 0x12002000L, + 0x10200000L, 0x12200000L, 0x10202000L, 0x12202000L, + 0x10000004L, 0x12000004L, 0x10002004L, 0x12002004L, + 0x10200004L, 0x12200004L, 0x10202004L, 0x12202004L, + 0x10000400L, 0x12000400L, 0x10002400L, 0x12002400L, + 0x10200400L, 0x12200400L, 0x10202400L, 0x12202400L, + 0x10000404L, 0x12000404L, 0x10002404L, 0x12002404L, + 0x10200404L, 0x12200404L, 0x10202404L, 0x12202404L, + }, + { + /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ + 0x00000000L, 0x00000001L, 0x00040000L, 0x00040001L, + 0x01000000L, 0x01000001L, 0x01040000L, 0x01040001L, + 0x00000002L, 0x00000003L, 0x00040002L, 0x00040003L, + 0x01000002L, 0x01000003L, 0x01040002L, 0x01040003L, + 0x00000200L, 0x00000201L, 0x00040200L, 0x00040201L, + 0x01000200L, 0x01000201L, 0x01040200L, 0x01040201L, + 0x00000202L, 0x00000203L, 0x00040202L, 0x00040203L, + 0x01000202L, 0x01000203L, 0x01040202L, 0x01040203L, + 0x08000000L, 0x08000001L, 0x08040000L, 0x08040001L, + 0x09000000L, 0x09000001L, 0x09040000L, 0x09040001L, + 0x08000002L, 0x08000003L, 0x08040002L, 0x08040003L, + 0x09000002L, 0x09000003L, 0x09040002L, 0x09040003L, + 0x08000200L, 0x08000201L, 0x08040200L, 0x08040201L, + 0x09000200L, 0x09000201L, 0x09040200L, 0x09040201L, + 0x08000202L, 0x08000203L, 0x08040202L, 0x08040203L, + 0x09000202L, 0x09000203L, 0x09040202L, 0x09040203L, + }, + { + /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ + 0x00000000L, 0x00100000L, 0x00000100L, 0x00100100L, + 0x00000008L, 0x00100008L, 0x00000108L, 0x00100108L, + 0x00001000L, 0x00101000L, 0x00001100L, 0x00101100L, + 0x00001008L, 0x00101008L, 0x00001108L, 0x00101108L, + 0x04000000L, 0x04100000L, 0x04000100L, 0x04100100L, + 0x04000008L, 0x04100008L, 0x04000108L, 0x04100108L, + 0x04001000L, 0x04101000L, 0x04001100L, 0x04101100L, + 0x04001008L, 0x04101008L, 0x04001108L, 0x04101108L, + 0x00020000L, 0x00120000L, 0x00020100L, 0x00120100L, + 0x00020008L, 0x00120008L, 0x00020108L, 0x00120108L, + 0x00021000L, 0x00121000L, 0x00021100L, 0x00121100L, + 0x00021008L, 0x00121008L, 0x00021108L, 0x00121108L, + 0x04020000L, 0x04120000L, 0x04020100L, 0x04120100L, + 0x04020008L, 0x04120008L, 0x04020108L, 0x04120108L, + 0x04021000L, 0x04121000L, 0x04021100L, 0x04121100L, + 0x04021008L, 0x04121008L, 0x04021108L, 0x04121108L, + }, + { + /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + 0x00000000L, 0x10000000L, 0x00010000L, 0x10010000L, + 0x00000004L, 0x10000004L, 0x00010004L, 0x10010004L, + 0x20000000L, 0x30000000L, 0x20010000L, 0x30010000L, + 0x20000004L, 0x30000004L, 0x20010004L, 0x30010004L, + 0x00100000L, 0x10100000L, 0x00110000L, 0x10110000L, + 0x00100004L, 0x10100004L, 0x00110004L, 0x10110004L, + 0x20100000L, 0x30100000L, 0x20110000L, 0x30110000L, + 0x20100004L, 0x30100004L, 0x20110004L, 0x30110004L, + 0x00001000L, 0x10001000L, 0x00011000L, 0x10011000L, + 0x00001004L, 0x10001004L, 0x00011004L, 0x10011004L, + 0x20001000L, 0x30001000L, 0x20011000L, 0x30011000L, + 0x20001004L, 0x30001004L, 0x20011004L, 0x30011004L, + 0x00101000L, 0x10101000L, 0x00111000L, 0x10111000L, + 0x00101004L, 0x10101004L, 0x00111004L, 0x10111004L, + 0x20101000L, 0x30101000L, 0x20111000L, 0x30111000L, + 0x20101004L, 0x30101004L, 0x20111004L, 0x30111004L, + }, + { + /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ + 0x00000000L, 0x08000000L, 0x00000008L, 0x08000008L, + 0x00000400L, 0x08000400L, 0x00000408L, 0x08000408L, + 0x00020000L, 0x08020000L, 0x00020008L, 0x08020008L, + 0x00020400L, 0x08020400L, 0x00020408L, 0x08020408L, + 0x00000001L, 0x08000001L, 0x00000009L, 0x08000009L, + 0x00000401L, 0x08000401L, 0x00000409L, 0x08000409L, + 0x00020001L, 0x08020001L, 0x00020009L, 0x08020009L, + 0x00020401L, 0x08020401L, 0x00020409L, 0x08020409L, + 0x02000000L, 0x0A000000L, 0x02000008L, 0x0A000008L, + 0x02000400L, 0x0A000400L, 0x02000408L, 0x0A000408L, + 0x02020000L, 0x0A020000L, 0x02020008L, 0x0A020008L, + 0x02020400L, 0x0A020400L, 0x02020408L, 0x0A020408L, + 0x02000001L, 0x0A000001L, 0x02000009L, 0x0A000009L, + 0x02000401L, 0x0A000401L, 0x02000409L, 0x0A000409L, + 0x02020001L, 0x0A020001L, 0x02020009L, 0x0A020009L, + 0x02020401L, 0x0A020401L, 0x02020409L, 0x0A020409L, + }, + { + /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ + 0x00000000L, 0x00000100L, 0x00080000L, 0x00080100L, + 0x01000000L, 0x01000100L, 0x01080000L, 0x01080100L, + 0x00000010L, 0x00000110L, 0x00080010L, 0x00080110L, + 0x01000010L, 0x01000110L, 0x01080010L, 0x01080110L, + 0x00200000L, 0x00200100L, 0x00280000L, 0x00280100L, + 0x01200000L, 0x01200100L, 0x01280000L, 0x01280100L, + 0x00200010L, 0x00200110L, 0x00280010L, 0x00280110L, + 0x01200010L, 0x01200110L, 0x01280010L, 0x01280110L, + 0x00000200L, 0x00000300L, 0x00080200L, 0x00080300L, + 0x01000200L, 0x01000300L, 0x01080200L, 0x01080300L, + 0x00000210L, 0x00000310L, 0x00080210L, 0x00080310L, + 0x01000210L, 0x01000310L, 0x01080210L, 0x01080310L, + 0x00200200L, 0x00200300L, 0x00280200L, 0x00280300L, + 0x01200200L, 0x01200300L, 0x01280200L, 0x01280300L, + 0x00200210L, 0x00200310L, 0x00280210L, 0x00280310L, + 0x01200210L, 0x01200310L, 0x01280210L, 0x01280310L, + }, + { + /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ + 0x00000000L, 0x04000000L, 0x00040000L, 0x04040000L, + 0x00000002L, 0x04000002L, 0x00040002L, 0x04040002L, + 0x00002000L, 0x04002000L, 0x00042000L, 0x04042000L, + 0x00002002L, 0x04002002L, 0x00042002L, 0x04042002L, + 0x00000020L, 0x04000020L, 0x00040020L, 0x04040020L, + 0x00000022L, 0x04000022L, 0x00040022L, 0x04040022L, + 0x00002020L, 0x04002020L, 0x00042020L, 0x04042020L, + 0x00002022L, 0x04002022L, 0x00042022L, 0x04042022L, + 0x00000800L, 0x04000800L, 0x00040800L, 0x04040800L, + 0x00000802L, 0x04000802L, 0x00040802L, 0x04040802L, + 0x00002800L, 0x04002800L, 0x00042800L, 0x04042800L, + 0x00002802L, 0x04002802L, 0x00042802L, 0x04042802L, + 0x00000820L, 0x04000820L, 0x00040820L, 0x04040820L, + 0x00000822L, 0x04000822L, 0x00040822L, 0x04040822L, + 0x00002820L, 0x04002820L, 0x00042820L, 0x04042820L, + 0x00002822L, 0x04002822L, 0x00042822L, 0x04042822L, + } +}; + + +static void DES_encrypt1(DES_LONG *data, DES_key_schedule *ks, int enc) +{ + register DES_LONG l, r, t, u; + register DES_LONG *s; + + r = data[0]; + l = data[1]; + + IP(r, l); + /* + * Things have been modified so that the initial rotate is done outside + * the loop. This required the DES_SPtrans values in sp.h to be rotated + * 1 bit to the right. One perl script later and things have a 5% speed + * up on a sparc2. Thanks to Richard Outerbridge for pointing this out. + */ + /* clear the top bits on machines with 8byte longs */ + /* shift left by 2 */ + r = ROTATE(r, 29) & 0xffffffffL; + l = ROTATE(l, 29) & 0xffffffffL; + + s = ks->ks->deslong; + /* + * I don't know if it is worth the effort of loop unrolling the inner + * loop + */ + if (enc) { + D_ENCRYPT(l, r, 0); /* 1 */ + D_ENCRYPT(r, l, 2); /* 2 */ + D_ENCRYPT(l, r, 4); /* 3 */ + D_ENCRYPT(r, l, 6); /* 4 */ + D_ENCRYPT(l, r, 8); /* 5 */ + D_ENCRYPT(r, l, 10); /* 6 */ + D_ENCRYPT(l, r, 12); /* 7 */ + D_ENCRYPT(r, l, 14); /* 8 */ + D_ENCRYPT(l, r, 16); /* 9 */ + D_ENCRYPT(r, l, 18); /* 10 */ + D_ENCRYPT(l, r, 20); /* 11 */ + D_ENCRYPT(r, l, 22); /* 12 */ + D_ENCRYPT(l, r, 24); /* 13 */ + D_ENCRYPT(r, l, 26); /* 14 */ + D_ENCRYPT(l, r, 28); /* 15 */ + D_ENCRYPT(r, l, 30); /* 16 */ + } else { + D_ENCRYPT(l, r, 30); /* 16 */ + D_ENCRYPT(r, l, 28); /* 15 */ + D_ENCRYPT(l, r, 26); /* 14 */ + D_ENCRYPT(r, l, 24); /* 13 */ + D_ENCRYPT(l, r, 22); /* 12 */ + D_ENCRYPT(r, l, 20); /* 11 */ + D_ENCRYPT(l, r, 18); /* 10 */ + D_ENCRYPT(r, l, 16); /* 9 */ + D_ENCRYPT(l, r, 14); /* 8 */ + D_ENCRYPT(r, l, 12); /* 7 */ + D_ENCRYPT(l, r, 10); /* 6 */ + D_ENCRYPT(r, l, 8); /* 5 */ + D_ENCRYPT(l, r, 6); /* 4 */ + D_ENCRYPT(r, l, 4); /* 3 */ + D_ENCRYPT(l, r, 2); /* 2 */ + D_ENCRYPT(r, l, 0); /* 1 */ + } + + /* rotate and clear the top bits on machines with 8byte longs */ + l = ROTATE(l, 3) & 0xffffffffL; + r = ROTATE(r, 3) & 0xffffffffL; + + FP(r, l); + data[0] = l; + data[1] = r; + l = r = t = u = 0; +} + + +static void DES_ecb_encrypt(const DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks, int enc) +{ + register DES_LONG l; + DES_LONG ll[2]; + const unsigned char *in = &(*input)[0]; + unsigned char *out = &(*output)[0]; + + c2l(in, l); + ll[0] = l; + c2l(in, l); + ll[1] = l; + DES_encrypt1(ll, ks, enc); + l = ll[0]; + l2c(l, out); + l = ll[1]; + l2c(l, out); + l = ll[0] = ll[1] = 0; +} + + +static void DES_set_key(const DES_cblock *key, DES_key_schedule *schedule) +{ + static const int shifts2[16] = + { 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0 }; + register DES_LONG c, d, t, s, t2; + register const unsigned char *in; + register DES_LONG *k; + register int i; + +#ifdef OPENBSD_DEV_CRYPTO + memcpy(schedule->key, key, sizeof(schedule->key)); + schedule->session = NULL; +#endif + k = &schedule->ks->deslong[0]; + in = &(*key)[0]; + + c2l(in, c); + c2l(in, d); + + /* + * do PC1 in 47 simple operations. Thanks to John Fletcher + * for the inspiration. + */ + PERM_OP(d, c, t, 4, 0x0f0f0f0fL); + HPERM_OP(c, t, -2, 0xcccc0000L); + HPERM_OP(d, t, -2, 0xcccc0000L); + PERM_OP(d, c, t, 1, 0x55555555L); + PERM_OP(c, d, t, 8, 0x00ff00ffL); + PERM_OP(d, c, t, 1, 0x55555555L); + d = (((d & 0x000000ffL) << 16L) | (d & 0x0000ff00L) | + ((d & 0x00ff0000L) >> 16L) | ((c & 0xf0000000L) >> 4L)); + c &= 0x0fffffffL; + + for (i = 0; i < ITERATIONS; i++) { + if (shifts2[i]) { + c = ((c >> 2L) | (c << 26L)); + d = ((d >> 2L) | (d << 26L)); + } else { + c = ((c >> 1L) | (c << 27L)); + d = ((d >> 1L) | (d << 27L)); + } + c &= 0x0fffffffL; + d &= 0x0fffffffL; + /* + * could be a few less shifts but I am to lazy at this point in time + * to investigate + */ + s = des_skb[0][(c) & 0x3f] | + des_skb[1][((c >> 6L) & 0x03) | ((c >> 7L) & 0x3c)] | + des_skb[2][((c >> 13L) & 0x0f) | ((c >> 14L) & 0x30)] | + des_skb[3][((c >> 20L) & 0x01) | ((c >> 21L) & 0x06) | + ((c >> 22L) & 0x38)]; + t = des_skb[4][(d) & 0x3f] | + des_skb[5][((d >> 7L) & 0x03) | ((d >> 8L) & 0x3c)] | + des_skb[6][(d >> 15L) & 0x3f] | + des_skb[7][((d >> 21L) & 0x0f) | ((d >> 22L) & 0x30)]; + + /* table contained 0213 4657 */ + t2 = ((t << 16L) | (s & 0x0000ffffL)) & 0xffffffffL; + *(k++) = ROTATE(t2, 30) & 0xffffffffL; + + t2 = ((s >> 16L) | (t & 0xffff0000L)); + *(k++) = ROTATE(t2, 26) & 0xffffffffL; + } +} + +/* End of import of OpenSSL DES encryption functions */ + +static int des_init(PPP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv) +{ + DES_key_schedule *ks = calloc(1, sizeof(DES_key_schedule)); + if (ks) { + + if (key) { + memcpy(ctx->key, key, 8); + } + + if (iv) { + memcpy(ctx->iv, iv, 8); + } + + if (key) { + DES_set_key((DES_cblock*) &ctx->key, ks); + } + + ctx->priv = ks; + return 1; + } + + return 0; +} + +static int des_update(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl) +{ + int offset = 0; + inl = inl / 8; + while (offset < inl) { + DES_ecb_encrypt((DES_cblock *)in + offset, (DES_cblock *)out + offset, + (DES_key_schedule*) ctx->priv, ctx->is_encr); + offset ++; + } + + *outl = offset * 8; + return 1; +} + +static int des_final(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ + return 1; +} + +static void des_clean(PPP_CIPHER_CTX *ctx) +{ + if (ctx->priv) { + free(ctx->priv); + ctx->priv = NULL; + } +} + +#endif + +static PPP_CIPHER ppp_des = { + .init_fn = des_init, + .update_fn = des_update, + .final_fn = des_final, + .clean_fn = des_clean, +}; + +const PPP_CIPHER *PPP_des_ecb(void) +{ + return &ppp_des; +} + diff --git a/pppd/ppp-md4.c b/pppd/ppp-md4.c new file mode 100644 index 0000000..305bfa8 --- /dev/null +++ b/pppd/ppp-md4.c @@ -0,0 +1,444 @@ +/* ppp-md4.c - MD4 Digest implementation + * + * 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. + * + * Sections of this code holds different copyright information. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "ppp-crypto-priv.h" + + +#ifdef OPENSSL_HAVE_MD4 +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define EVP_MD_CTX_free EVP_MD_CTX_destroy +#define EVP_MD_CTX_new EVP_MD_CTX_create +#endif + + +static int md4_init(PPP_MD_CTX *ctx) +{ + if (ctx) { + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + if (mctx) { + if (EVP_DigestInit(mctx, EVP_md4())) { + ctx->priv = mctx; + return 1; + } + EVP_MD_CTX_free(mctx); + } + } + return 0; +} + +static int md4_update(PPP_MD_CTX *ctx, const void *data, size_t len) +{ + if (EVP_DigestUpdate((EVP_MD_CTX*) ctx->priv, data, len)) { + return 1; + } + return 0; +} + +static int md4_final(PPP_MD_CTX *ctx, unsigned char *out, unsigned int *len) +{ + if (EVP_DigestFinal((EVP_MD_CTX*) ctx->priv, out, len)) { + return 1; + } + return 0; +} + +static void md4_clean(PPP_MD_CTX *ctx) +{ + if (ctx->priv) { + EVP_MD_CTX_free(ctx->priv); + ctx->priv = NULL; + } +} + + +#else // !OPENSSL_HAVE_MD4 + +#define TRUE 1 +#define FALSE 0 + +/* +** ******************************************************************** +** md4.c -- Implementation of MD4 Message Digest Algorithm ** +** Updated: 2/16/90 by Ronald L. Rivest ** +** (C) 1990 RSA Data Security, Inc. ** +** ******************************************************************** +*/ + +/* +** To use MD4: +** -- Include md4.h in your program +** -- Declare an MDstruct MD to hold the state of the digest +** computation. +** -- Initialize MD using MDbegin(&MD) +** -- For each full block (64 bytes) X you wish to process, call +** MD4Update(&MD,X,512) +** (512 is the number of bits in a full block.) +** -- For the last block (less than 64 bytes) you wish to process, +** MD4Update(&MD,X,n) +** where n is the number of bits in the partial block. A partial +** block terminates the computation, so every MD computation +** should terminate by processing a partial block, even if it +** has n = 0. +** -- The message digest is available in MD.buffer[0] ... +** MD.buffer[3]. (Least-significant byte of each word +** should be output first.) +** -- You can print out the digest using MDprint(&MD) +*/ + +/* Implementation notes: +** This implementation assumes that ints are 32-bit quantities. +*/ + +/* MDstruct is the data structure for a message digest computation. +*/ +typedef struct { + unsigned int buffer[4]; /* Holds 4-word result of MD computation */ + unsigned char count[8]; /* Number of bits processed so far */ + unsigned int done; /* Nonzero means MD computation finished */ +} MD4_CTX; + + +/* Compile-time declarations of MD4 "magic constants". +*/ +#define I0 0x67452301 /* Initial values for MD buffer */ +#define I1 0xefcdab89 +#define I2 0x98badcfe +#define I3 0x10325476 +#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */ +#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */ +/* C2 and C3 are from Knuth, The Art of Programming, Volume 2 +** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley. +** Table 2, page 660. +*/ + +#define fs1 3 /* round 1 shift amounts */ +#define fs2 7 +#define fs3 11 +#define fs4 19 +#define gs1 3 /* round 2 shift amounts */ +#define gs2 5 +#define gs3 9 +#define gs4 13 +#define hs1 3 /* round 3 shift amounts */ +#define hs2 9 +#define hs3 11 +#define hs4 15 + +/* Compile-time macro declarations for MD4. +** Note: The "rot" operator uses the variable "tmp". +** It assumes tmp is declared as unsigned int, so that the >> +** operator will shift in zeros rather than extending the sign bit. +*/ +#define f(X,Y,Z) ((X&Y) | ((~X)&Z)) +#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z)) +#define h(X,Y,Z) (X^Y^Z) +#define rot(X,S) (tmp=X,(tmp<>(32-S))) +#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s) +#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s) +#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s) + +/* MD4print(MDp) +** Print message digest buffer MDp as 32 hexadecimal digits. +** Order is from low-order byte of buffer[0] to high-order byte of +** buffer[3]. +** Each byte is printed with high-order hexadecimal digit first. +** This is a user-callable routine. +*/ +static void +MD4Print(MD4_CTX *MDp) +{ + int i,j; + for (i=0;i<4;i++) + for (j=0;j<32;j=j+8) + printf("%02x",(MDp->buffer[i]>>j) & 0xFF); +} + +/* MD4Init(MDp) +** Initialize message digest buffer MDp. +** This is a user-callable routine. +*/ +static void +MD4Init(MD4_CTX *MDp) +{ + int i; + MDp->buffer[0] = I0; + MDp->buffer[1] = I1; + MDp->buffer[2] = I2; + MDp->buffer[3] = I3; + for (i=0;i<8;i++) MDp->count[i] = 0; + MDp->done = 0; +} + +/* MDblock(MDp,X) +** Update message digest buffer MDp->buffer using 16-word data block X. +** Assumes all 16 words of X are full of data. +** Does not update MDp->count. +** This routine is not user-callable. +*/ +static void +MDblock(MD4_CTX *MDp, unsigned char *Xb) +{ + register unsigned int tmp, A, B, C, D; + unsigned int X[16]; + int i; + + for (i = 0; i < 16; ++i) { + X[i] = Xb[0] + (Xb[1] << 8) + (Xb[2] << 16) + (Xb[3] << 24); + Xb += 4; + } + + A = MDp->buffer[0]; + B = MDp->buffer[1]; + C = MDp->buffer[2]; + D = MDp->buffer[3]; + /* Update the message digest buffer */ + ff(A , B , C , D , 0 , fs1); /* Round 1 */ + ff(D , A , B , C , 1 , fs2); + ff(C , D , A , B , 2 , fs3); + ff(B , C , D , A , 3 , fs4); + ff(A , B , C , D , 4 , fs1); + ff(D , A , B , C , 5 , fs2); + ff(C , D , A , B , 6 , fs3); + ff(B , C , D , A , 7 , fs4); + ff(A , B , C , D , 8 , fs1); + ff(D , A , B , C , 9 , fs2); + ff(C , D , A , B , 10 , fs3); + ff(B , C , D , A , 11 , fs4); + ff(A , B , C , D , 12 , fs1); + ff(D , A , B , C , 13 , fs2); + ff(C , D , A , B , 14 , fs3); + ff(B , C , D , A , 15 , fs4); + gg(A , B , C , D , 0 , gs1); /* Round 2 */ + gg(D , A , B , C , 4 , gs2); + gg(C , D , A , B , 8 , gs3); + gg(B , C , D , A , 12 , gs4); + gg(A , B , C , D , 1 , gs1); + gg(D , A , B , C , 5 , gs2); + gg(C , D , A , B , 9 , gs3); + gg(B , C , D , A , 13 , gs4); + gg(A , B , C , D , 2 , gs1); + gg(D , A , B , C , 6 , gs2); + gg(C , D , A , B , 10 , gs3); + gg(B , C , D , A , 14 , gs4); + gg(A , B , C , D , 3 , gs1); + gg(D , A , B , C , 7 , gs2); + gg(C , D , A , B , 11 , gs3); + gg(B , C , D , A , 15 , gs4); + hh(A , B , C , D , 0 , hs1); /* Round 3 */ + hh(D , A , B , C , 8 , hs2); + hh(C , D , A , B , 4 , hs3); + hh(B , C , D , A , 12 , hs4); + hh(A , B , C , D , 2 , hs1); + hh(D , A , B , C , 10 , hs2); + hh(C , D , A , B , 6 , hs3); + hh(B , C , D , A , 14 , hs4); + hh(A , B , C , D , 1 , hs1); + hh(D , A , B , C , 9 , hs2); + hh(C , D , A , B , 5 , hs3); + hh(B , C , D , A , 13 , hs4); + hh(A , B , C , D , 3 , hs1); + hh(D , A , B , C , 11 , hs2); + hh(C , D , A , B , 7 , hs3); + hh(B , C , D , A , 15 , hs4); + MDp->buffer[0] += A; + MDp->buffer[1] += B; + MDp->buffer[2] += C; + MDp->buffer[3] += D; +} + +/* MD4Update(MDp,X,count) +** Input: X -- a pointer to an array of unsigned characters. +** count -- the number of bits of X to use. +** (if not a multiple of 8, uses high bits of last byte.) +** Update MDp using the number of bits of X given by count. +** This is the basic input routine for an MD4 user. +** The routine completes the MD computation when count < 512, so +** every MD computation should end with one call to MD4Update with a +** count less than 512. A call with count 0 will be ignored if the +** MD has already been terminated (done != 0), so an extra call with +** count 0 can be given as a "courtesy close" to force termination +** if desired. +*/ +static void +MD4Update(MD4_CTX *MDp, unsigned char *X, unsigned int count) +{ + unsigned int i, tmp, bit, byte, mask; + unsigned char XX[64]; + unsigned char *p; + + /* return with no error if this is a courtesy close with count + ** zero and MDp->done is true. + */ + if (count == 0 && MDp->done) return; + /* check to see if MD is already done and report error */ + if (MDp->done) + { printf("\nError: MD4Update MD already done."); return; } + + /* Add count to MDp->count */ + tmp = count; + p = MDp->count; + while (tmp) + { tmp += *p; + *p++ = tmp; + tmp = tmp >> 8; + } + + /* Process data */ + if (count == 512) + { /* Full block of data to handle */ + MDblock(MDp,X); + } + else if (count > 512) /* Check for count too large */ + { + printf("\nError: MD4Update called with illegal count value %d.", + count); + return; + } + else /* partial block -- must be last block so finish up */ + { + /* Find out how many bytes and residual bits there are */ + byte = count >> 3; + bit = count & 7; + /* Copy X into XX since we need to modify it */ + if (count) + for (i=0;i<=byte;i++) XX[i] = X[i]; + for (i=byte+1;i<64;i++) XX[i] = 0; + /* Add padding '1' bit and low-order zeros in last byte */ + mask = 1 << (7 - bit); + XX[byte] = (XX[byte] | mask) & ~( mask - 1); + /* If room for bit count, finish up with this block */ + if (byte <= 55) + { + for (i=0;i<8;i++) XX[56+i] = MDp->count[i]; + MDblock(MDp,XX); + } + else /* need to do two blocks to finish up */ + { + MDblock(MDp,XX); + for (i=0;i<56;i++) XX[i] = 0; + for (i=0;i<8;i++) XX[56+i] = MDp->count[i]; + MDblock(MDp,XX); + } + /* Set flag saying we're done with MD computation */ + MDp->done = 1; + } +} + +/* +** Finish up MD4 computation and return message digest. +*/ +static void +MD4Final(unsigned char *buf, MD4_CTX *MD) +{ + int i, j; + unsigned int w; + + MD4Update(MD, NULL, 0); + for (i = 0; i < 4; ++i) { + w = MD->buffer[i]; + for (j = 0; j < 4; ++j) { + *buf++ = w; + w >>= 8; + } + } +} + +/* +** End of md4.c +****************************(cut)***********************************/ + +static int md4_init(PPP_MD_CTX *ctx) +{ + if (ctx) { + MD4_CTX *mctx = calloc(1, sizeof(MD4_CTX)); + if (mctx) { + MD4Init(mctx); + ctx->priv = mctx; + return 1; + } + } + return 0; +} + +static int md4_update(PPP_MD_CTX *ctx, const void *data, size_t len) +{ +#if defined(__NetBSD__) + /* NetBSD uses the libc md4 routines which take bytes instead of bits */ + int mdlen = len; +#else + int mdlen = len * 8; +#endif + + /* Internal MD4Update can take at most 64 bytes at a time */ + while (mdlen > 512) { + MD4Update((MD4_CTX*) ctx->priv, (unsigned char*) data, 512); + data += 64; + mdlen -= 512; + } + MD4Update((MD4_CTX*) ctx->priv, (unsigned char*) data, mdlen); + return 1; +} + +static int md4_final(PPP_MD_CTX *ctx, unsigned char *out, unsigned int *len) +{ + MD4Final(out, (MD4_CTX*) ctx->priv); + return 1; +} + +static void md4_clean(PPP_MD_CTX *ctx) +{ + if (ctx->priv) { + free(ctx->priv); + ctx->priv = NULL; + } +} + +#endif + +static PPP_MD ppp_md4 = { + .init_fn = md4_init, + .update_fn = md4_update, + .final_fn = md4_final, + .clean_fn = md4_clean, +}; + +const PPP_MD *PPP_md4(void) +{ + return &ppp_md4; +} diff --git a/pppd/ppp-md5.c b/pppd/ppp-md5.c new file mode 100644 index 0000000..dffb046 --- /dev/null +++ b/pppd/ppp-md5.c @@ -0,0 +1,451 @@ +/* ppp-md5.c - MD5 Digest implementation + * + * 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. + * + * Sections of this code holds different copyright information. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "ppp-crypto-priv.h" + +#ifdef OPENSSL_HAVE_MD5 +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define EVP_MD_CTX_free EVP_MD_CTX_destroy +#define EVP_MD_CTX_new EVP_MD_CTX_create +#endif + +static int md5_init(PPP_MD_CTX *ctx) +{ + if (ctx) { + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + if (mctx) { + if (EVP_DigestInit((EVP_MD_CTX*) mctx, EVP_md5())) { + ctx->priv = mctx; + return 1; + } + EVP_MD_CTX_free(mctx); + } + } + return 0; +} + +static int md5_update(PPP_MD_CTX *ctx, const void *data, size_t len) +{ + if (EVP_DigestUpdate((EVP_MD_CTX*) ctx->priv, data, len)) { + return 1; + } + return 0; +} + +static int md5_final(PPP_MD_CTX *ctx, unsigned char *out, unsigned int *len) +{ + if (EVP_DigestFinal((EVP_MD_CTX*) ctx->priv, out, len)) { + return 1; + } + return 0; +} + +static void md5_clean(PPP_MD_CTX *ctx) +{ + if (ctx->priv) { + EVP_MD_CTX_free((EVP_MD_CTX*) ctx->priv); + ctx->priv = NULL; + } +} + +#else // !OPENSSL_HAVE_MD5 + +/* + *********************************************************************** + ** md5.c -- the source code for MD5 routines ** + ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. ** + *********************************************************************** + */ + +/* + *********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + *********************************************************************** + */ + + +/* typedef a 32-bit type */ +#ifdef _LP64 +typedef unsigned int UINT4; +typedef int INT4; +#else +typedef unsigned long UINT4; +typedef long INT4; +#endif +#define _UINT4_T + +/* Data structure for MD5 (Message-Digest) computation */ +typedef struct { + UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ + UINT4 buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ + unsigned char digest[16]; /* actual digest after MD5Final call */ +} MD5_CTX; + + +/* + *********************************************************************** + ** Message-digest routines: ** + ** To form the message digest for a message M ** + ** (1) Initialize a context buffer mdContext using MD5_Init ** + ** (2) Call MD5_Update on mdContext and M ** + ** (3) Call MD5_Final on mdContext ** + ** The message digest is now in mdContext->digest[0...15] ** + *********************************************************************** + */ + +/* forward declaration */ +static void Transform (UINT4 *buf, UINT4 *in); + +static unsigned char PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G, H and I are basic MD5 functions */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s, ac) \ + {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) \ + {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) \ + {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) \ + {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +#ifdef __STDC__ +#define UL(x) x##U +#else +#define UL(x) x +#endif + +/* The routine MD5_Init initializes the message-digest context + mdContext. All fields are set to zero. + */ +static void MD5_Init (MD5_CTX *mdContext) +{ + mdContext->i[0] = mdContext->i[1] = (UINT4)0; + + /* Load magic initialization constants. + */ + mdContext->buf[0] = (UINT4)0x67452301; + mdContext->buf[1] = (UINT4)0xefcdab89; + mdContext->buf[2] = (UINT4)0x98badcfe; + mdContext->buf[3] = (UINT4)0x10325476; +} + +/* The routine MD5Update updates the message-digest context to + account for the presence of each of the characters inBuf[0..inLen-1] + in the message whose digest is being computed. + */ +static void MD5_Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen) +{ + UINT4 in[16]; + int mdi; + unsigned int i, ii; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ + if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) + mdContext->i[1]++; + mdContext->i[0] += ((UINT4)inLen << 3); + mdContext->i[1] += ((UINT4)inLen >> 29); + + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +/* The routine MD5Final terminates the message-digest computation and + ends with the desired message digest in mdContext->digest[0...15]. + */ +static void MD5_Final (unsigned char hash[], MD5_CTX *mdContext) +{ + UINT4 in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + MD5_Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + Transform (mdContext->buf, in); + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); + mdContext->digest[ii+1] = + (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); + mdContext->digest[ii+2] = + (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); + mdContext->digest[ii+3] = + (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); + } + memcpy(hash, mdContext->digest, 16); +} + +/* Basic MD5 step. Transforms buf based on in. + */ +static void Transform (UINT4 *buf, UINT4 *in) +{ + UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */ + FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */ + FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */ + FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */ + FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */ + FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */ + FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */ + FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */ + FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */ + FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */ + FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */ + FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */ + FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */ + FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */ + FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */ + FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */ + + /* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */ + GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */ + GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */ + GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */ + GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */ + GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */ + GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */ + GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */ + GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */ + GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */ + GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */ + GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */ + GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */ + GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */ + GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */ + GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */ + + /* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */ + HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */ + HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */ + HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */ + HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */ + HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */ + HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */ + HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */ + HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */ + HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */ + HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */ + HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */ + HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */ + HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */ + HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */ + HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */ + + /* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */ + II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */ + II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */ + II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */ + II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */ + II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */ + II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */ + II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */ + II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */ + II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */ + II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */ + II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */ + II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */ + II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */ + II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */ + II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */ + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/* + *********************************************************************** + ** End of md5.c ** + ******************************** (cut) ******************************** + */ + +static int md5_init(PPP_MD_CTX *ctx) +{ + if (ctx) { + MD5_CTX *md5 = calloc(1, sizeof(MD5_CTX)); + if (md5 != NULL) { + MD5_Init(md5); + ctx->priv = md5; + return 1; + } + } + return 0; +} + +static int md5_update(PPP_MD_CTX *ctx, const void *data, size_t len) +{ + MD5_Update((MD5_CTX*) ctx->priv, (void*) data, len); + return 1; +} + +static int md5_final(PPP_MD_CTX *ctx, unsigned char *out, unsigned int *len) +{ + MD5_Final(out, (MD5_CTX*) ctx->priv); + return 1; +} + +static void md5_clean(PPP_MD_CTX *ctx) +{ + if (ctx->priv) { + free(ctx->priv); + ctx->priv = NULL; + } +} + +#endif + +static PPP_MD ppp_md5 = { + .init_fn = md5_init, + .update_fn = md5_update, + .final_fn = md5_final, + .clean_fn = md5_clean, +}; + +const PPP_MD *PPP_md5(void) +{ + return &ppp_md5; +} + diff --git a/pppd/ppp-sha1.c b/pppd/ppp-sha1.c new file mode 100644 index 0000000..437c8ba --- /dev/null +++ b/pppd/ppp-sha1.c @@ -0,0 +1,312 @@ +/* ppp-sha1.c - SHA1 Digest implementation + * + * 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. + * + * Sections of this code holds different copyright information. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "ppp-crypto-priv.h" + + +/* #define SHA1HANDSOFF * Copies data before messing with it. */ +#ifdef OPENSSL_HAVE_SHA +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define EVP_MD_CTX_free EVP_MD_CTX_destroy +#define EVP_MD_CTX_new EVP_MD_CTX_create +#endif + +static int sha1_init(PPP_MD_CTX *ctx) +{ + if (ctx) { + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + if (mctx) { + if (EVP_DigestInit(mctx, EVP_sha1())) { + ctx->priv = mctx; + return 1; + } + EVP_MD_CTX_free(mctx); + } + } + return 0; +} + +static int sha1_update(PPP_MD_CTX *ctx, const void *data, size_t len) +{ + if (EVP_DigestUpdate((EVP_MD_CTX*) ctx->priv, data, len)) { + return 1; + } + return 0; +} + +static int sha1_final(PPP_MD_CTX *ctx, unsigned char *out, unsigned int *len) +{ + if (EVP_DigestFinal((EVP_MD_CTX*) ctx->priv, out, len)) { + return 1; + } + return 0; +} + +static void sha1_clean(PPP_MD_CTX *ctx) +{ + if (ctx->priv) { + EVP_MD_CTX_free((EVP_MD_CTX*) ctx->priv); + ctx->priv = NULL; + } +} + + +#else // !OPENSSL_HAVE_SHA + +/* + * ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c + * + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + * + * Test Vectors (from FIPS PUB 180-1) + * "abc" + * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + * A million repetitions of "a" + * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F + */ + +#include +#include /* htonl() */ + +typedef struct { + u_int32_t state[5]; + u_int32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + + +static void +SHA1_Transform(u_int32_t[5], const unsigned char[64]); + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#define blk0(i) (block->l[i] = htonl(block->l[i])) +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +static void +SHA1_Transform(u_int32_t state[5], const unsigned char buffer[64]) +{ + u_int32_t a, b, c, d, e; + typedef union { + unsigned char c[64]; + u_int32_t l[16]; + } CHAR64LONG16; + CHAR64LONG16 *block; + +#ifdef SHA1HANDSOFF + static unsigned char workspace[64]; + block = (CHAR64LONG16 *) workspace; + memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16 *) buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* SHA1Init - Initialize new context */ + +static void +SHA1_Init(SHA1_CTX *context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +static void +SHA1_Update(SHA1_CTX *context, const unsigned char *data, unsigned int len) +{ + unsigned int i, j; + + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; + context->count[1] += (len >> 29); + i = 64 - j; + while (len >= i) { + memcpy(&context->buffer[j], data, i); + SHA1_Transform(context->state, context->buffer); + data += i; + len -= i; + i = 64; + j = 0; + } + + memcpy(&context->buffer[j], data, len); +} + + +/* Add padding and return the message digest. */ + +static void +SHA1_Final(unsigned char digest[20], SHA1_CTX *context) +{ + u_int32_t i, j; + unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + SHA1_Update(context, (unsigned char *) "\200", 1); + while ((context->count[0] & 504) != 448) { + SHA1_Update(context, (unsigned char *) "\0", 1); + } + SHA1_Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + /* Wipe variables */ + i = j = 0; + memset(context->buffer, 0, 64); + memset(context->state, 0, 20); + memset(context->count, 0, 8); + memset(&finalcount, 0, 8); +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ + SHA1Transform(context->state, context->buffer); +#endif +} + +static int sha1_init(PPP_MD_CTX *ctx) +{ + if (ctx) { + SHA1_CTX *mctx = calloc(1, sizeof(SHA1_CTX)); + if (mctx) { + SHA1_Init(mctx); + ctx->priv = mctx; + return 1; + } + } + return 0; +} + +static int sha1_update(PPP_MD_CTX* ctx, const void *data, size_t len) +{ + SHA1_Update((SHA1_CTX*) ctx->priv, (void*) data, len); + return 1; +} + +static int sha1_final(PPP_MD_CTX *ctx, unsigned char *out, unsigned int *len) +{ + SHA1_Final(out, (SHA1_CTX*) ctx->priv); + return 1; +} + +static void sha1_clean(PPP_MD_CTX *ctx) +{ + if (ctx->priv) { + free(ctx->priv); + ctx->priv = NULL; + } +} + +#endif + +static PPP_MD ppp_sha1 = { + .init_fn = sha1_init, + .update_fn = sha1_update, + .final_fn = sha1_final, + .clean_fn = sha1_clean, +}; + +const PPP_MD *PPP_sha1(void) +{ + return &ppp_sha1; +} + diff --git a/pppd/pppcrypt.c b/pppd/pppcrypt.c index a954d62..cc4f5f7 100644 --- a/pppd/pppcrypt.c +++ b/pppd/pppcrypt.c @@ -28,19 +28,72 @@ * 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. + * + * Sections of this code holds different copyright information. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include +#include -#include "pppd.h" #include "pppcrypt.h" +#include "ppp-crypto.h" + + +/* + * DES_set_odd_parity function are imported from openssl 3.0 project with the + * follwoing license: + * + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +typedef unsigned char DES_cblock[8]; +#define DES_KEY_SZ (sizeof(DES_cblock)) -static u_char -Get7Bits(u_char *input, int startBit) +static const unsigned char odd_parity[256] = { + 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, + 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, + 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, + 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, + 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, + 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, + 97, 97, 98, 98, 100, 100, 103, 103, 104, 104, 107, 107, 109, 109, 110, + 110, + 112, 112, 115, 115, 117, 117, 118, 118, 121, 121, 122, 122, 124, 124, 127, + 127, + 128, 128, 131, 131, 133, 133, 134, 134, 137, 137, 138, 138, 140, 140, 143, + 143, + 145, 145, 146, 146, 148, 148, 151, 151, 152, 152, 155, 155, 157, 157, 158, + 158, + 161, 161, 162, 162, 164, 164, 167, 167, 168, 168, 171, 171, 173, 173, 174, + 174, + 176, 176, 179, 179, 181, 181, 182, 182, 185, 185, 186, 186, 188, 188, 191, + 191, + 193, 193, 194, 194, 196, 196, 199, 199, 200, 200, 203, 203, 205, 205, 206, + 206, + 208, 208, 211, 211, 213, 213, 214, 214, 217, 217, 218, 218, 220, 220, 223, + 223, + 224, 224, 227, 227, 229, 229, 230, 230, 233, 233, 234, 234, 236, 236, 239, + 239, + 241, 241, 242, 242, 244, 244, 247, 247, 248, 248, 251, 251, 253, 253, 254, + 254 +}; + +static void DES_set_odd_parity(DES_cblock *key) +{ + unsigned int i; + for (i = 0; i < DES_KEY_SZ; i++) + (*key)[i] = odd_parity[(*key)[i]]; +} + +static unsigned char +Get7Bits(const unsigned char *input, int startBit) { unsigned int word; @@ -53,7 +106,7 @@ Get7Bits(u_char *input, int startBit) } static void -MakeKey(u_char *key, u_char *des_key) +MakeKey(const unsigned char *key, unsigned char *des_key) { /* key IN 56 bit DES key missing parity bits */ /* des_key OUT 64 bit DES key with parity bits added */ @@ -66,117 +119,162 @@ MakeKey(u_char *key, u_char *des_key) des_key[6] = Get7Bits(key, 42); des_key[7] = Get7Bits(key, 49); -#ifndef USE_CRYPT DES_set_odd_parity((DES_cblock *)des_key); -#endif } -#ifdef USE_CRYPT -/* - * in == 8-byte string (expanded version of the 56-bit key) - * out == 64-byte string where each byte is either 1 or 0 - * Note that the low-order "bit" is always ignored by by setkey() - */ -static void -Expand(u_char *in, u_char *out) +#include + +int +DesEncrypt(unsigned char *clear, unsigned char *key, unsigned char *cipher) { - int j, c; - int i; - - for (i = 0; i < 64; in++){ - c = *in; - for (j = 7; j >= 0; j--) - *out++ = (c >> j) & 01; - i += 8; + int retval = 0; + unsigned int clen = 0; + unsigned char des_key[8]; + + PPP_CIPHER_CTX *ctx = PPP_CIPHER_CTX_new(); + if (ctx) { + + MakeKey(key, des_key); + + if (PPP_CipherInit(ctx, PPP_des_ecb(), des_key, NULL, 1)) { + + if (PPP_CipherUpdate(ctx, cipher, &clen, clear, 8)) { + + if (PPP_CipherFinal(ctx, cipher + clen, &clen)) { + + retval = 1; + } + } } -} + + PPP_CIPHER_CTX_free(ctx); + } -/* The inverse of Expand - */ -static void -Collapse(u_char *in, u_char *out) -{ - int j; - int i; - unsigned int c; - - for (i = 0; i < 64; i += 8, out++) { - c = 0; - for (j = 7; j >= 0; j--, in++) - c |= *in << j; - *out = c & 0xff; - } + return (retval); } -bool -DesSetkey(u_char *key) +int +DesDecrypt(unsigned char *cipher, unsigned char *key, unsigned char *clear) { - u_char des_key[8]; - u_char crypt_key[66]; - - MakeKey(key, des_key); - Expand(des_key, crypt_key); - errno = 0; - setkey((const char *)crypt_key); - if (errno != 0) - return (0); - return (1); -} + int retval = 0; + unsigned int clen = 0; + unsigned char des_key[8]; -bool -DesEncrypt(u_char *clear, u_char *cipher) -{ - u_char des_input[66]; - - Expand(clear, des_input); - errno = 0; - encrypt((char *)des_input, 0); - if (errno != 0) - return (0); - Collapse(des_input, cipher); - return (1); -} + PPP_CIPHER_CTX *ctx = PPP_CIPHER_CTX_new(); + if (ctx) { -bool -DesDecrypt(u_char *cipher, u_char *clear) -{ - u_char des_input[66]; - - Expand(cipher, des_input); - errno = 0; - encrypt((char *)des_input, 1); - if (errno != 0) - return (0); - Collapse(des_input, clear); - return (1); + MakeKey(key, des_key); + + if (PPP_CipherInit(ctx, PPP_des_ecb(), des_key, NULL, 0)) { + + if (PPP_CipherUpdate(ctx, clear, &clen, cipher, 8)) { + + if (PPP_CipherFinal(ctx, clear + clen, &clen)) { + + retval = 1; + } + } + } + + PPP_CIPHER_CTX_free(ctx); + } + + return (retval); } -#else /* USE_CRYPT */ -static DES_key_schedule key_schedule; +#ifdef UNIT_TEST_PPPCRYPT + +#include +#include -bool -DesSetkey(u_char *key) +/** + * The test-vectors are taken from RFC2759. + */ +int test_encrypt() { - DES_cblock des_key; - MakeKey(key, des_key); - DES_set_key(&des_key, &key_schedule); - return (1); + unsigned char Challenge[8] = { + 0xD0, 0x2E, 0x43, 0x86, 0xBC, 0xE9, 0x12, 0x26 + }; + + unsigned char ZPasswordHash[21] = { + 0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6, + 0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE + }; + + unsigned char expected[24] = { + 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E, + 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54, + 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF + }; + unsigned char response[24] = {}; + unsigned int retval = 0; + + DesEncrypt(Challenge, ZPasswordHash + 0, response + 0); + DesEncrypt(Challenge, ZPasswordHash + 7, response + 8); + DesEncrypt(Challenge, ZPasswordHash + 14, response + 16); + + return memcmp(response, expected, sizeof(response)) == 0; } -bool -DesEncrypt(u_char *clear, u_char *cipher) +int test_decrypt() { - DES_ecb_encrypt((DES_cblock *)clear, (DES_cblock *)cipher, - &key_schedule, 1); - return (1); + unsigned char Challenge[8] = { + 0xD0, 0x2E, 0x43, 0x86, 0xBC, 0xE9, 0x12, 0x26 + }; + + unsigned char ZPasswordHash[21] = { + 0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6, + 0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE + }; + + unsigned char Response[24] = { + 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E, + 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54, + 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF + }; + unsigned char Output[8]; + unsigned int failure = 0; + + if (DesDecrypt(Response + 0, ZPasswordHash + 0, Output)) { + failure += memcmp(Challenge, Output, sizeof(Challenge)); + } + + if (DesDecrypt(Response + 8, ZPasswordHash + 7, Output)) { + failure += memcmp(Challenge, Output, sizeof(Challenge)); + } + + if (DesDecrypt(Response +16, ZPasswordHash +14, Output)) { + failure += memcmp(Challenge, Output, sizeof(Challenge)); + } + + return failure == 0; } -bool -DesDecrypt(u_char *cipher, u_char *clear) +int main(int argc, char *argv[]) { - DES_ecb_encrypt((DES_cblock *)cipher, (DES_cblock *)clear, - &key_schedule, 0); - return (1); + int failure = 0; + + if (!PPP_crypto_init()) { + printf("Couldn't initialize crypto test\n"); + return -1; + } + + if (!test_encrypt()) { + printf("CHAP DES encryption test failed\n"); + failure++; + } + + if (!test_decrypt()) { + printf("CHAP DES decryption test failed\n"); + failure++; + } + + if (!PPP_crypto_deinit()) { + printf("Couldn't deinitialize crypto test\n"); + return -1; + } + + return failure; } -#endif /* USE_CRYPT */ +#endif diff --git a/pppd/pppcrypt.h b/pppd/pppcrypt.h index fff396c..9083594 100644 --- a/pppd/pppcrypt.h +++ b/pppd/pppcrypt.h @@ -2,7 +2,9 @@ * pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1 * * Extracted from chap_ms.c by James Carlson. + * Updated to better reflect RFC2759 by Eivind Naess * + * Copyright (c) 2022 Eivind Naess. All rights reserved. * Copyright (c) 1995 Eric Rosenquist. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,16 +36,40 @@ #include "pppdconf.h" -#ifdef HAVE_CRYPT_H -#include -#endif - -#ifndef USE_CRYPT -#include -#endif +/** + * This is the DES encrypt functions as described by RFC2759. + * + * Parameters: + * unsigned char *clear: + * A 8 byte input array to be encrypted + * + * unsigned char *key: + * A raw 7-byte array to be expanded to 8 with odd-parity + * + * unsigned char *cipher: + * A 8 byte outut array providing space for the output data + * + * DesEncrypt returns 1 on success + */ +int DesEncrypt(unsigned char *clear, unsigned char *key, + unsigned char *cipher); -extern bool DesSetkey(u_char *); -extern bool DesEncrypt(u_char *, u_char *); -extern bool DesDecrypt(u_char *, u_char *); +/** + * This is the DES decrypt functions as described by RFC2759. + * + * Parameters: + * unsigned char *cipher: + * A 8 byte input array to be decrypted + * + * unsigned char *key: + * A raw 7-byte array to be expanded to a 8-byte key with odd-parity + * + * unsigned char *clear: + * A 8 byte output array providing space for the output data + * + * DesDecrypt returns 1 on success + */ +int DesDecrypt(unsigned char *cipher, unsigned char *key, + unsigned char *clear); #endif /* PPP_PPPCRYPT_H */ diff --git a/pppd/pppd.h b/pppd/pppd.h index bd9faf0..d4bc043 100644 --- a/pppd/pppd.h +++ b/pppd/pppd.h @@ -358,6 +358,7 @@ extern bool multilink; /* enable multilink operation */ extern bool noendpoint; /* don't send or accept endpt. discrim. */ extern char *bundle_name; /* bundle name for multilink */ extern bool dump_options; /* print out option values */ +extern bool show_options; /* show all option names and descriptions */ extern bool dryrun; /* check everything, print options, exit */ extern int child_wait; /* # seconds to wait for children at end */ @@ -776,7 +777,8 @@ int override_value(char *, int, const char *); /* override value if permitted by priority */ void print_options(printer_func, void *); /* print out values of all options */ - +void showopts(void); + /* show all option names and description */ int parse_dotted_ip(char *, u_int32_t *); /* diff --git a/pppd/pppdconf.h.in b/pppd/pppdconf.h.in index 64c37f7..ad25dca 100644 --- a/pppd/pppdconf.h.in +++ b/pppd/pppdconf.h.in @@ -45,18 +45,6 @@ /* Have PEAP authentication support */ #undef PPP_WITH_PEAP -/* Use included des included with pppd */ -#undef USE_CRYPT - -/* Use included md4 included with pppd */ -#undef USE_MD4 - -/* Use included md5 included with pppd */ -#undef USE_MD5 - -/* Use included sha included with pppd */ -#undef USE_SHA - /* The pppd version */ #undef PPPD_VERSION diff --git a/pppd/sha1.c b/pppd/sha1.c deleted file mode 100644 index 4fc5345..0000000 --- a/pppd/sha1.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c - * - * SHA-1 in C - * By Steve Reid - * 100% Public Domain - * - * Test Vectors (from FIPS PUB 180-1) - * "abc" - * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D - * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 - * A million repetitions of "a" - * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* #define SHA1HANDSOFF * Copies data before messing with it. */ - -#include -#include -#include /* htonl() */ -#include "sha1.h" - -static void -SHA1_Transform(u_int32_t[5], const unsigned char[64]); - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -/* blk0() and blk() perform the initial expand. */ -/* I got the idea of expanding during the round function from SSLeay */ -#define blk0(i) (block->l[i] = htonl(block->l[i])) -#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ - ^block->l[(i+2)&15]^block->l[i&15],1)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); - - -/* Hash a single 512-bit block. This is the core of the algorithm. */ - -static void -SHA1_Transform(u_int32_t state[5], const unsigned char buffer[64]) -{ - u_int32_t a, b, c, d, e; - typedef union { - unsigned char c[64]; - u_int32_t l[16]; - } CHAR64LONG16; - CHAR64LONG16 *block; - -#ifdef SHA1HANDSOFF - static unsigned char workspace[64]; - block = (CHAR64LONG16 *) workspace; - memcpy(block, buffer, 64); -#else - block = (CHAR64LONG16 *) buffer; -#endif - /* Copy context->state[] to working vars */ - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - /* Wipe variables */ - a = b = c = d = e = 0; -} - - -/* SHA1Init - Initialize new context */ - -void -SHA1_Init(SHA1_CTX *context) -{ - /* SHA1 initialization constants */ - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - - -/* Run your data through this. */ - -void -SHA1_Update(SHA1_CTX *context, const unsigned char *data, unsigned int len) -{ - unsigned int i, j; - - j = (context->count[0] >> 3) & 63; - if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; - context->count[1] += (len >> 29); - i = 64 - j; - while (len >= i) { - memcpy(&context->buffer[j], data, i); - SHA1_Transform(context->state, context->buffer); - data += i; - len -= i; - i = 64; - j = 0; - } - - memcpy(&context->buffer[j], data, len); -} - - -/* Add padding and return the message digest. */ - -void -SHA1_Final(unsigned char digest[20], SHA1_CTX *context) -{ - u_int32_t i, j; - unsigned char finalcount[8]; - - for (i = 0; i < 8; i++) { - finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] - >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ - } - SHA1_Update(context, (unsigned char *) "\200", 1); - while ((context->count[0] & 504) != 448) { - SHA1_Update(context, (unsigned char *) "\0", 1); - } - SHA1_Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ - for (i = 0; i < 20; i++) { - digest[i] = (unsigned char) - ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); - } - /* Wipe variables */ - i = j = 0; - memset(context->buffer, 0, 64); - memset(context->state, 0, 20); - memset(context->count, 0, 8); - memset(&finalcount, 0, 8); -#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ - SHA1Transform(context->state, context->buffer); -#endif -} - diff --git a/pppd/sha1.h b/pppd/sha1.h deleted file mode 100644 index 2325133..0000000 --- a/pppd/sha1.h +++ /dev/null @@ -1,35 +0,0 @@ -/* sha1.h */ - -#ifndef PPP_SHA1_H -#define PPP_SHA1_H - -#include "pppdconf.h" - -#ifndef USE_SHA -#include - -#define SHA1_CTX SHA_CTX -#define SHA1_SIGNATURE_SIZE SHA_DIGEST_LENGTH - -#else - -#ifndef SHA1_SIGNATURE_SIZE -#ifdef SHA_DIGESTSIZE -#define SHA1_SIGNATURE_SIZE SHA_DIGESTSIZE -#else -#define SHA1_SIGNATURE_SIZE 20 -#endif -#endif - -typedef struct { - u_int32_t state[5]; - u_int32_t count[2]; - unsigned char buffer[64]; -} SHA1_CTX; - -extern void SHA1_Init(SHA1_CTX *); -extern void SHA1_Update(SHA1_CTX *, const unsigned char *, unsigned int); -extern void SHA1_Final(unsigned char[SHA1_SIGNATURE_SIZE], SHA1_CTX *); - -#endif /* USE_SHA */ -#endif /* PPP_SHA1_H */