summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@ozlabs.org>2022-09-09 12:05:36 +1000
committerGitHub <noreply@github.com>2022-09-09 12:05:36 +1000
commit3ae4027842d48c3c92996ffb8443b9b320c1c775 (patch)
tree63f50adf4630825eeed262e00d7aedc09cf1f53c
parent87640b7b5ceb562146a1c4b820c7e151ff078eec (diff)
parenta25e52a87c3f5cbe2c2264f4e7c4c02439ac6717 (diff)
downloadppp-3ae4027842d48c3c92996ffb8443b9b320c1c775.tar.gz
Merge pull request #362 from enaess/ppp-crypto
Create an new API that allows us to abstract the use of the standard crypto functions
-rw-r--r--configure.ac29
-rw-r--r--pppd/.gitignore1
-rw-r--r--pppd/Makefile.am42
-rw-r--r--pppd/chap-md5.c74
-rw-r--r--pppd/chap_ms.c198
-rw-r--r--pppd/chap_ms.h17
-rw-r--r--pppd/eap.c369
-rw-r--r--pppd/eap.h1
-rw-r--r--pppd/main.c4
-rw-r--r--pppd/md4.h68
-rw-r--r--pppd/md5.h71
-rw-r--r--pppd/mppe.c143
-rw-r--r--pppd/mppe.h6
-rw-r--r--pppd/plugins/radius/Makefile.am15
-rw-r--r--pppd/plugins/radius/md5.c29
-rw-r--r--pppd/plugins/radius/radius.c198
-rw-r--r--pppd/plugins/radius/radiusclient.h2
-rw-r--r--pppd/plugins/winbind.c5
-rw-r--r--pppd/ppp-crypto-priv.h69
-rw-r--r--pppd/ppp-crypto.c499
-rw-r--r--pppd/ppp-crypto.h100
-rw-r--r--pppd/ppp-des.c730
-rw-r--r--pppd/ppp-md4.c (renamed from pppd/md4.c)179
-rw-r--r--pppd/ppp-md5.c (renamed from pppd/md5.c)162
-rw-r--r--pppd/ppp-sha1.c (renamed from pppd/sha1.c)164
-rw-r--r--pppd/pppcrypt.c290
-rw-r--r--pppd/pppcrypt.h46
-rw-r--r--pppd/pppdconf.h.in12
-rw-r--r--pppd/sha1.h35
29 files changed, 2828 insertions, 730 deletions
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 <t_pwd.h>
#include <t_server.h>
#include <t_client.h>
-#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, " <M2%.*B%s>", 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, " <M1%.*B%s>", 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, " <Response%.*B%s>", 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..8d5f32b 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);
@@ -581,6 +584,7 @@ main(int argc, char *argv[])
}
}
+ PPP_crypto_deinit();
die(status);
return 0;
}
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 <openssl/md4.h>
-#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.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 <openssl/md5.h>
-#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/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 <pppd/md5.h>
+#include <stddef.h>
-void rc_md5_calc (unsigned char *output, unsigned char *input, unsigned int inlen)
+#include <pppd/ppp-crypto.h>
+
+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 <pppd/chap_ms.h>
#ifdef PPP_WITH_MPPE
#include <pppd/mppe.h>
-#include <pppd/md5.h>
+#include <pppd/ppp-crypto.h>
#endif
#endif
#include <pppd/fsm.h>
@@ -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 <pppd/fsm.h>
#include <pppd/ipcp.h>
#include <pppd/mppe.h>
+#include <pppd/ppp-crypto.h>
#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 <stdlib.h>
+#include <string.h>
+
+#include "ppp-crypto.h"
+#include "ppp-crypto-priv.h"
+
+#ifdef PPP_WITH_OPENSSL
+#include <openssl/opensslv.h>
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/provider.h>
+struct crypto_ctx {
+
+ OSSL_PROVIDER *legacy;
+ OSSL_PROVIDER *provider;
+} g_crypto_ctx;
+#endif
+
+PPP_MD_CTX *PPP_MD_CTX_new()
+{
+ return (PPP_MD_CTX*) calloc(1, sizeof(PPP_MD_CTX));
+}
+
+void PPP_MD_CTX_free(PPP_MD_CTX* ctx)
+{
+ if (ctx) {
+ if (ctx->md.clean_fn) {
+ ctx->md.clean_fn(ctx);
+ }
+ free(ctx);
+ }
+}
+
+int PPP_DigestInit(PPP_MD_CTX *ctx, const PPP_MD *type)
+{
+ if (ctx) {
+ ctx->md = *type;
+ if (ctx->md.init_fn) {
+ return ctx->md.init_fn(ctx);
+ }
+ }
+ return 0;
+}
+
+int PPP_DigestUpdate(PPP_MD_CTX *ctx, const void *data, size_t length)
+{
+ if (ctx && ctx->md.update_fn) {
+ return ctx->md.update_fn(ctx, data, length);
+ }
+ return 0;
+}
+
+int PPP_DigestFinal(PPP_MD_CTX *ctx, unsigned char *out, unsigned int *outlen)
+{
+ if (ctx && ctx->md.final_fn) {
+ return ctx->md.final_fn(ctx, out, outlen);
+ }
+ return 0;
+}
+
+PPP_CIPHER_CTX *PPP_CIPHER_CTX_new(void)
+{
+ return calloc(1, sizeof(PPP_CIPHER_CTX));
+}
+
+void PPP_CIPHER_CTX_free(PPP_CIPHER_CTX *ctx)
+{
+ if (ctx) {
+ if (ctx->cipher.clean_fn) {
+ ctx->cipher.clean_fn(ctx);
+ }
+ memset(ctx->iv, 0, sizeof(ctx->iv));
+ memset(ctx->key, 0, sizeof(ctx->key));
+ free(ctx);
+ }
+}
+
+int PPP_CipherInit(PPP_CIPHER_CTX *ctx, const PPP_CIPHER *cipher, const unsigned char *key, const unsigned char *iv, int encr)
+{
+ if (ctx && cipher) {
+ ctx->is_encr = encr;
+ ctx->cipher = *cipher;
+ if (ctx->cipher.init_fn) {
+ ctx->cipher.init_fn(ctx, key, iv);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+int PPP_CipherUpdate(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl)
+{
+ if (ctx && ctx->cipher.update_fn) {
+ return ctx->cipher.update_fn(ctx, out, outl, in, inl);
+ }
+ return 0;
+}
+
+int PPP_CipherFinal(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
+{
+ if (ctx && ctx->cipher.final_fn) {
+ return ctx->cipher.final_fn(ctx, out, outl);
+ }
+ return 0;
+}
+
+int PPP_crypto_init()
+{
+ int retval = 0;
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ g_crypto_ctx.legacy = OSSL_PROVIDER_load(NULL, "legacy");
+ if (g_crypto_ctx.legacy == NULL)
+ {
+ goto done;
+ }
+
+ g_crypto_ctx.provider = OSSL_PROVIDER_load(NULL, "default");
+ if (g_crypto_ctx.provider == NULL)
+ {
+ goto done;
+ }
+#endif
+ retval = 1;
+
+done:
+
+ return retval;
+}
+
+int PPP_crypto_deinit()
+{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ if (g_crypto_ctx.legacy) {
+ OSSL_PROVIDER_unload(g_crypto_ctx.legacy);
+ g_crypto_ctx.legacy = NULL;
+ }
+
+ if (g_crypto_ctx.provider) {
+ OSSL_PROVIDER_unload(g_crypto_ctx.provider);
+ g_crypto_ctx.provider = NULL;
+ }
+#endif
+ return 1;
+}
+
+#ifdef UNIT_TEST
+#include <stdio.h>
+
+int test_md4()
+{
+ PPP_MD_CTX* ctx = NULL;
+ int success = 0;
+
+ unsigned char data[84] = {
+ 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69,
+ 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
+ 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
+ 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
+ 0x6b, 0x65, 0x79, 0x2e
+ };
+
+ unsigned int hash_len;
+ unsigned char hash[MD4_DIGEST_LENGTH];
+ unsigned char result[MD4_DIGEST_LENGTH] = {
+ 0x58, 0xcb, 0x37, 0x91, 0x1d, 0x06, 0x7b, 0xdf,
+ 0xfd, 0x48, 0x6d, 0x87, 0x4a, 0x35, 0x5b, 0xd4
+ };
+
+ ctx = PPP_MD_CTX_new();
+ if (ctx) {
+
+ if (PPP_DigestInit(ctx, PPP_md4())) {
+
+ if (PPP_DigestUpdate(ctx, &data, sizeof(data))) {
+
+ hash_len = sizeof(hash);
+ if (PPP_DigestFinal(ctx, hash, &hash_len)) {
+
+ if (memcmp(hash, result, MD4_DIGEST_LENGTH) == 0) {
+ success = 1;
+ }
+ }
+ }
+ }
+ PPP_MD_CTX_free(ctx);
+ }
+
+ return success;
+}
+
+int test_md5()
+{
+ PPP_MD_CTX* ctx = NULL;
+ int success = 0;
+
+ unsigned char data[84] = {
+ 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69,
+ 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
+ 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
+ 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
+ 0x6b, 0x65, 0x79, 0x2e
+ };
+
+ unsigned int hash_len;
+ unsigned char hash[MD5_DIGEST_LENGTH];
+ unsigned char result[MD5_DIGEST_LENGTH] = {
+ 0x8b, 0xe3, 0x5e, 0x2c, 0x9f, 0x95, 0xbf, 0x4e,
+ 0x16, 0xe4, 0x53, 0xbe, 0x52, 0xf4, 0xbc, 0x4e
+ };
+
+ ctx = PPP_MD_CTX_new();
+ if (ctx) {
+
+ if (PPP_DigestInit(ctx, PPP_md5())) {
+
+ if (PPP_DigestUpdate(ctx, &data, sizeof(data))) {
+
+ hash_len = sizeof(hash);
+ if (PPP_DigestFinal(ctx, hash, &hash_len)) {
+
+ if (memcmp(hash, result, MD5_DIGEST_LENGTH) == 0) {
+ success = 1;
+ }
+ }
+ }
+ }
+ PPP_MD_CTX_free(ctx);
+ }
+
+ return success;
+}
+
+int test_sha()
+{
+ PPP_MD_CTX* ctx = NULL;
+ int success = 0;
+
+ unsigned char data[84] = {
+ 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69,
+ 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
+ 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
+ 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
+ 0x6b, 0x65, 0x79, 0x2e
+ };
+
+ unsigned int hash_len;
+ unsigned char hash[SHA_DIGEST_LENGTH];
+ unsigned char result[SHA_DIGEST_LENGTH] = {
+ 0xa8, 0x03, 0xae, 0x21, 0x30, 0xd8, 0x40, 0xbe,
+ 0x27, 0xa3, 0x47, 0xc7, 0x7a, 0x90, 0xe6, 0xa3,
+ 0x5b, 0xd5, 0x0e, 0x45
+ };
+
+ ctx = PPP_MD_CTX_new();
+ if (ctx) {
+
+ if (PPP_DigestInit(ctx, PPP_sha1())) {
+
+ if (PPP_DigestUpdate(ctx, &data, sizeof(data))) {
+
+ hash_len = sizeof(hash);
+ if (PPP_DigestFinal(ctx, hash, &hash_len)) {
+
+ if (memcmp(hash, result, SHA_DIGEST_LENGTH) == 0) {
+ success = 1;
+ }
+ }
+ }
+ }
+ PPP_MD_CTX_free(ctx);
+ }
+
+ return success;
+}
+
+int test_des_encrypt()
+{
+ PPP_CIPHER_CTX* ctx = NULL;
+ int success = 0;
+
+ unsigned char key[8] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ };
+
+ unsigned char plain[80] = {
+ 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69,
+ 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
+ 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
+ 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20
+ };
+ unsigned char expect[80] = {
+ 0x45, 0xdb, 0x80, 0x45, 0x16, 0xd0, 0x6d, 0x60,
+ 0x92, 0x23, 0x4b, 0xd3, 0x9d, 0x36, 0xb8, 0x1a,
+ 0xa4, 0x1a, 0xf7, 0xb1, 0x60, 0xfb, 0x74, 0x16,
+ 0xa6, 0xdc, 0xe1, 0x14, 0xb7, 0xed, 0x48, 0x5a,
+ 0x2b, 0xed, 0x68, 0x9d, 0x19, 0xd6, 0xb1, 0xb8,
+ 0x91, 0xff, 0xea, 0x62, 0xac, 0xe7, 0x49, 0xdd,
+ 0xfa, 0x4d, 0xa4, 0x01, 0x3f, 0xea, 0xca, 0xb4,
+ 0xb6, 0xdc, 0xd3, 0x04, 0x45, 0x07, 0x74, 0xed,
+ 0xa6, 0xdc, 0xe1, 0x14, 0xb7, 0xed, 0x48, 0x5a,
+ 0xbb, 0x9b, 0x13, 0x31, 0xf4, 0xa9, 0x32, 0x49
+ };
+
+ unsigned char cipher[80] = {};
+ int cipher_len = 0;
+ int offset = 0;
+
+
+ ctx = PPP_CIPHER_CTX_new();
+ if (ctx) {
+
+ if (PPP_CipherInit(ctx, PPP_des_ecb(), key, NULL, 1)) {
+
+ if (PPP_CipherUpdate(ctx, cipher, &cipher_len, plain, sizeof(plain))) {
+
+ offset += cipher_len;
+
+ if (PPP_CipherFinal(ctx, cipher+offset, &cipher_len)) {
+
+ if (memcmp(cipher, expect, 80) == 0) {
+
+ success = 1;
+ }
+ }
+ }
+ }
+ PPP_CIPHER_CTX_free(ctx);
+ }
+
+ return success;
+}
+
+
+int test_des_decrypt()
+{
+ PPP_CIPHER_CTX* ctx = NULL;
+ int success = 0;
+
+ unsigned char key[8] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ };
+
+ unsigned char cipher[80] = {
+ 0x45, 0xdb, 0x80, 0x45, 0x16, 0xd0, 0x6d, 0x60,
+ 0x92, 0x23, 0x4b, 0xd3, 0x9d, 0x36, 0xb8, 0x1a,
+ 0xa4, 0x1a, 0xf7, 0xb1, 0x60, 0xfb, 0x74, 0x16,
+ 0xa6, 0xdc, 0xe1, 0x14, 0xb7, 0xed, 0x48, 0x5a,
+ 0x2b, 0xed, 0x68, 0x9d, 0x19, 0xd6, 0xb1, 0xb8,
+ 0x91, 0xff, 0xea, 0x62, 0xac, 0xe7, 0x49, 0xdd,
+ 0xfa, 0x4d, 0xa4, 0x01, 0x3f, 0xea, 0xca, 0xb4,
+ 0xb6, 0xdc, 0xd3, 0x04, 0x45, 0x07, 0x74, 0xed,
+ 0xa6, 0xdc, 0xe1, 0x14, 0xb7, 0xed, 0x48, 0x5a,
+ 0xbb, 0x9b, 0x13, 0x31, 0xf4, 0xa9, 0x32, 0x49
+ };
+
+ unsigned char expect[80] = {
+ 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69,
+ 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
+ 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
+ 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20
+ };
+
+ unsigned char plain[80] = {};
+ int outlen = 0;
+ int offset = 0;
+
+ ctx = PPP_CIPHER_CTX_new();
+ if (ctx) {
+
+ if (PPP_CipherInit(ctx, PPP_des_ecb(), key, NULL, 0)) {
+
+ if (PPP_CipherUpdate(ctx, plain, &outlen, cipher, sizeof(cipher))) {
+
+ offset += outlen;
+
+ if (PPP_CipherFinal(ctx, plain+offset, &outlen)) {
+
+ if (memcmp(plain, expect, 80) == 0) {
+
+ success = 1;
+ }
+ }
+ }
+ }
+ PPP_CIPHER_CTX_free(ctx);
+ }
+
+ return success;
+}
+
+int main(int argc, char *argv[])
+{
+ int failure = 0;
+
+ if (!PPP_crypto_init()) {
+ printf("Couldn't initialize crypto test\n");
+ return -1;
+ }
+
+ if (!test_md4()) {
+ printf("MD4 test failed\n");
+ failure++;
+ }
+
+ if (!test_md5()) {
+ printf("MD5 test failed\n");
+ failure++;
+ }
+
+ if (!test_sha()) {
+ printf("SHA test failed\n");
+ failure++;
+ }
+
+ if (!test_des_encrypt()) {
+ printf("DES encryption test failed\n");
+ failure++;
+ }
+
+ if (!test_des_decrypt()) {
+ printf("DES decryption test failed\n");
+ failure++;
+ }
+
+ if (!PPP_crypto_deinit()) {
+ printf("Couldn't deinitialize crypto test\n");
+ return -1;
+ }
+
+ return failure;
+}
+
+#endif
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 <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ppp-crypto-priv.h"
+
+#ifdef OPENSSL_HAVE_DES
+
+#include <openssl/evp.h>
+
+#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/md4.c b/pppd/ppp-md4.c
index 88f3413..305bfa8 100644
--- a/pppd/md4.c
+++ b/pppd/ppp-md4.c
@@ -1,3 +1,97 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+
+#include "ppp-crypto-priv.h"
+
+
+#ifdef OPENSSL_HAVE_MD4
+#include <openssl/evp.h>
+
+#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 **
@@ -30,18 +124,15 @@
/* 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
+/* MDstruct is the data structure for a message digest computation.
*/
-#include <stdio.h>
-#include "md4.h"
-#include "pppd.h"
+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".
*/
@@ -89,7 +180,7 @@
** Each byte is printed with high-order hexadecimal digit first.
** This is a user-callable routine.
*/
-void
+static void
MD4Print(MD4_CTX *MDp)
{
int i,j;
@@ -102,7 +193,7 @@ MD4Print(MD4_CTX *MDp)
** Initialize message digest buffer MDp.
** This is a user-callable routine.
*/
-void
+static void
MD4Init(MD4_CTX *MDp)
{
int i;
@@ -204,7 +295,7 @@ MDblock(MD4_CTX *MDp, unsigned char *Xb)
** count 0 can be given as a "courtesy close" to force termination
** if desired.
*/
-void
+static void
MD4Update(MD4_CTX *MDp, unsigned char *X, unsigned int count)
{
unsigned int i, tmp, bit, byte, mask;
@@ -272,7 +363,7 @@ MD4Update(MD4_CTX *MDp, unsigned char *X, unsigned int count)
/*
** Finish up MD4 computation and return message digest.
*/
-void
+static void
MD4Final(unsigned char *buf, MD4_CTX *MD)
{
int i, j;
@@ -291,3 +382,63 @@ MD4Final(unsigned char *buf, MD4_CTX *MD)
/*
** 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/md5.c b/pppd/ppp-md5.c
index 9fb3397..dffb046 100644
--- a/pppd/md5.c
+++ b/pppd/ppp-md5.c
@@ -1,4 +1,91 @@
+/* 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 <stdlib.h>
+#include <string.h>
+
+#include "ppp-crypto-priv.h"
+
+#ifdef OPENSSL_HAVE_MD5
+#include <openssl/evp.h>
+
+#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
/*
***********************************************************************
@@ -33,12 +120,25 @@
***********************************************************************
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
+
+/* 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;
-#include <string.h>
-#include "md5.h"
/*
***********************************************************************
@@ -106,7 +206,7 @@ static unsigned char PADDING[64] = {
/* The routine MD5_Init initializes the message-digest context
mdContext. All fields are set to zero.
*/
-void MD5_Init (MD5_CTX *mdContext)
+static void MD5_Init (MD5_CTX *mdContext)
{
mdContext->i[0] = mdContext->i[1] = (UINT4)0;
@@ -122,7 +222,7 @@ void MD5_Init (MD5_CTX *mdContext)
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)
+static void MD5_Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen)
{
UINT4 in[16];
int mdi;
@@ -157,7 +257,7 @@ void MD5_Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen)
/* 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)
+static void MD5_Final (unsigned char hash[], MD5_CTX *mdContext)
{
UINT4 in[16];
int mdi;
@@ -301,3 +401,51 @@ static void Transform (UINT4 *buf, UINT4 *in)
** 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/sha1.c b/pppd/ppp-sha1.c
index 4fc5345..437c8ba 100644
--- a/pppd/sha1.c
+++ b/pppd/ppp-sha1.c
@@ -1,10 +1,102 @@
+/* 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 <stdlib.h>
+#include <stddef.h>
+
+#include "ppp-crypto-priv.h"
+
+
+/* #define SHA1HANDSOFF * Copies data before messing with it. */
+#ifdef OPENSSL_HAVE_SHA
+#include <openssl/evp.h>
+
+#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 <steve@edmweb.com>
* 100% Public Domain
- *
+ *
* Test Vectors (from FIPS PUB 180-1)
* "abc"
* A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
@@ -14,16 +106,15 @@
* 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* #define SHA1HANDSOFF * Copies data before messing with it. */
-
#include <string.h>
-#include <time.h>
#include <netinet/in.h> /* htonl() */
-#include "sha1.h"
+
+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]);
@@ -103,7 +194,7 @@ SHA1_Transform(u_int32_t state[5], const unsigned char buffer[64])
/* SHA1Init - Initialize new context */
-void
+static void
SHA1_Init(SHA1_CTX *context)
{
/* SHA1 initialization constants */
@@ -118,7 +209,7 @@ SHA1_Init(SHA1_CTX *context)
/* Run your data through this. */
-void
+static void
SHA1_Update(SHA1_CTX *context, const unsigned char *data, unsigned int len)
{
unsigned int i, j;
@@ -142,7 +233,7 @@ SHA1_Update(SHA1_CTX *context, const unsigned char *data, unsigned int len)
/* Add padding and return the message digest. */
-void
+static void
SHA1_Final(unsigned char digest[20], SHA1_CTX *context)
{
u_int32_t i, j;
@@ -172,3 +263,50 @@ SHA1_Final(unsigned char digest[20], SHA1_CTX *context)
#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 <errno.h>
+#include <stddef.h>
-#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 <openssl/evp.h>
+
+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 <string.h>
+#include <stdio.h>
-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 <crypt.h>
-#endif
-
-#ifndef USE_CRYPT
-#include <openssl/des.h>
-#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/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.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 <openssl/sha.h>
-
-#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 */