initial code drop

This commit is contained in:
Dag-Erling Smørgrav 2014-07-04 11:18:53 +00:00 committed by des
parent 2e28935df9
commit ae99587ba4
93 changed files with 10601 additions and 0 deletions

14
Makefile.am Normal file
View file

@ -0,0 +1,14 @@
# $Id$
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = include lib t
EXTRA_DIST = \
CREDITS \
HISTORY \
INSTALL \
LICENSE \
README \
RELNOTES \
autogen.sh

44
autogen.des Executable file
View file

@ -0,0 +1,44 @@
#!/bin/sh
#
# $Id$
#
has() {
which "$@" >/dev/null 2>&1
}
# BullseyeCoverage needs to know exactly which compiler we're using
if has clang clang++ ; then
echo "using Clang"
export CC="${CC:-clang}"
export CPP="${CPP:-${CC} -E}"
export CXX="${CXX:-clang++}"
elif has gcc g++ ; then
echo "using GCC"
export CC="${CC:-gcc}"
export CPP="${CPP:-gcc -E}"
export CXX="${CXX:-g++}"
else
echo "WARNING: using default compiler," \
"coverage analysis may not work"
fi
set -e
if has cov01 ; then
cov01 -u
cov01 -0
fi
. ./autogen.sh
./configure \
--with-openssl \
--with-rsaref \
--enable-developer-warnings \
--enable-werror \
"$@"
if has cov01 ; then
cov01 -o
fi

10
autogen.sh Executable file
View file

@ -0,0 +1,10 @@
#!/bin/sh
#
# $Id$
#
libtoolize --copy --force
aclocal -I m4
autoheader
automake -a -c --foreign
autoconf

114
configure.ac Normal file
View file

@ -0,0 +1,114 @@
AC_PREREQ([2.63])
AC_REVISION([$Id$])
AC_INIT([cryb.to], [trunk], [des@des.no], [crybto], [http://cryb.to/])
AC_CONFIG_SRCDIR([include/cryb/to.h])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([foreign])
AM_CONFIG_HEADER([include/config.h])
# C compiler and features
AC_LANG(C)
AC_PROG_CC
AC_PROG_CC_STDC
AC_PROG_CPP
AC_C_CONST
AC_C_RESTRICT
AC_C_VOLATILE
AC_C_BIGENDIAN
# libtool
LT_PREREQ([2.2.6])
LT_INIT()
# other programs
AC_PROG_INSTALL
# Include benchmarks in unit tests
AC_ARG_WITH([benchmarks],
AC_HELP_STRING([--with-benchmarks],
[include benchmarks in unit tests]),
[],
[with_benchmarks=no])
AM_CONDITIONAL([WITH_BENCHMARKS], [test x"$with_benchmarks" = x"yes"])
# OpenSSL versions of the unit tests for comparison
AC_ARG_WITH([openssl],
AC_HELP_STRING([--with-openssl],
[build unit tests with OpenSSL support]),
[],
[with_openssl=no])
AM_CONDITIONAL([WITH_OPENSSL], [test x"$with_openssl" = x"yes"])
# RSAREF versions of the unit tests for comparison
AC_ARG_WITH([rsaref],
AC_HELP_STRING([--with-rsaref],
[build unit tests with RSAREF support]),
[],
[with_rsaref=no])
AM_CONDITIONAL([WITH_RSAREF], [test x"$with_rsaref" = x"yes"])
# Documentation
AC_ARG_WITH([doc],
AC_HELP_STRING([--without-doc],
[do not build the documentation]),
[],
[with_doc=yes])
AM_CONDITIONAL([WITH_DOC], [test x"$with_doc" = x"yes"])
# Message digests
AC_ARG_WITH([digest],
AC_HELP_STRING([--without-digest],
[do not build the message digest library and tools]),
[],
[with_digest=yes])
AM_CONDITIONAL([WITH_DIGEST], [test x"$with_digest" = x"yes"])
# Message authentication codes
AC_ARG_WITH([mac],
AC_HELP_STRING([--without-mac],
[do not build the message authentication code library and tools]),
[],
[with_mac=yes])
AM_CONDITIONAL([WITH_MAC], [test x"$with_digest" = x"yes"])
# OATH
AC_ARG_WITH([oath],
AC_HELP_STRING([--without-oath],
[do not build the OATH library and tools]),
[],
[with_oath=yes])
AM_CONDITIONAL([WITH_OATH], [test x"$with_oath" = x"yes"])
# Developer-friendly compiler flags
AC_ARG_ENABLE([developer-warnings],
AS_HELP_STRING([--enable-developer-warnings],
[enable strict warnings (default is NO)]),
[CFLAGS="${CFLAGS} -Wall -Wextra"])
AC_ARG_ENABLE([debugging-symbols],
AS_HELP_STRING([--enable-debugging-symbols],
[enable debugging symbols (default is NO)]),
[CFLAGS="${CFLAGS} -O0 -g -fno-inline"])
AC_ARG_ENABLE([werror],
AS_HELP_STRING([--enable-werror],
[use -Werror (default is NO)]),
[CFLAGS="${CFLAGS} -Werror"])
AC_CHECK_HEADERS([endian.h sys/endian.h])
AC_CHECK_FUNCS([strlcat strlcmp strlcpy])
AC_CONFIG_FILES([
Makefile
include/Makefile
include/cryb/Makefile
lib/Makefile
lib/core/Makefile
lib/digest/Makefile
lib/enc/Makefile
lib/mac/Makefile
lib/oath/Makefile
lib/rand/Makefile
lib/rsaref/Makefile
t/Makefile
])
AC_OUTPUT

3
include/Makefile.am Normal file
View file

@ -0,0 +1,3 @@
# $Id$
SUBDIRS = cryb

28
include/cryb/Makefile.am Normal file
View file

@ -0,0 +1,28 @@
# $Id$
crybdir = $(includedir)/cryb
cryb_HEADERS = \
algorithm.h \
attributes.h \
bitwise.h \
digest.h \
hmac.h \
hotp.h \
mac.h \
md5.h \
oath.h \
oath_constants.h \
oath_types.h \
rand.h \
rfc3986.h \
rfc4648.h \
sha1.h \
to.h \
totp.h \
version.h
noinst_HEADERS = \
coverage.h \
impl.h \
nocoverage.h

49
include/cryb/algorithm.h Normal file
View file

@ -0,0 +1,49 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#ifndef CRYB_ALGORITHM_H_INCLUDED
#define CRYB_ALGORITHM_H_INCLUDED
typedef enum algorithm_type {
digest_algorithm,
mac_algorithm,
} algorithm_type;
typedef struct algorithm {
algorithm_type type;
const char *name;
} algorithm;
#endif

49
include/cryb/attributes.h Normal file
View file

@ -0,0 +1,49 @@
/*-
* Copyright (c) 2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#ifndef CRYB_ATTRIBUTES_H_INCLUDED
#define CRYB_ATTRIBUTES_H_INCLUDED
#if defined(__GNUC__) || defined(__clang__)
# define CRYB_PRINTF(fmt, arg) __attribute__((format(printf, fmt, arg)))
# define CRYB_NORETURN __attribute__((noreturn))
# define CRYB_UNUSED __attribute__((unused))
# define CRYB_USED __attribute__((used))
#else
# define CRYB_PRINTF(fmt, arg)
# define CRYB_NORETURN
# define CRYB_UNUSED
# define CRYB_USED
#endif
#endif

53
include/cryb/bitwise.h Normal file
View file

@ -0,0 +1,53 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#ifndef CRYB_BITWISE_H_INCLUDED
#define CRYB_BITWISE_H_INCLUDED
static inline uint32_t
rol(uint32_t i, int n)
{
return (i << n | i >> (32 - n));
}
static inline uint32_t
ror(uint32_t i, int n)
{
return (i << (32 - n) | i >> n);
}
#endif

54
include/cryb/coverage.h Normal file
View file

@ -0,0 +1,54 @@
/*-
* Copyright (c) 2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#ifndef CRYB_COVERAGE_H_INCLUDED
#define CRYB_COVERAGE_H_INCLUDED
#if _BullseyeCoverage
# define CRYB_DISABLE_COVERAGE _Pragma("BullseyeCoverage save off")
# define CRYB_RESTORE_COVERAGE _Pragma("BullseyeCoverage restore")
#else
# define CRYB_DISABLE_COVERAGE
# define CRYB_RESTORE_COVERAGE
#endif
/*
* Use at end of switch which has no default case
*/
#define CRYB_NO_DEFAULT_CASE \
CRYB_DISABLE_COVERAGE \
default: \
(void)0; \
CRYB_RESTORE_COVERAGE
#endif

107
include/cryb/ctype.h Normal file
View file

@ -0,0 +1,107 @@
/*-
* Copyright (c) 2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#ifndef CRYB_CTYPE_H_INCLUDED
#define CRYB_CTYPE_H_INCLUDED
/*
* Evaluates to non-zero if the argument is a digit.
*/
#define is_digit(ch) \
(ch >= '0' && ch <= '9')
/*
* Evaluates to non-zero if the argument is a hex digit.
*/
#define is_xdigit(ch) \
((ch >= '0' && ch <= '9') || \
(ch >= 'a' && ch <= 'f') || \
(ch >= 'A' && ch <= 'F'))
/*
* Evaluates to non-zero if the argument is an uppercase letter.
*/
#define is_upper(ch) \
(ch >= 'A' && ch <= 'Z')
/*
* Evaluates to non-zero if the argument is a lowercase letter.
*/
#define is_lower(ch) \
(ch >= 'a' && ch <= 'z')
/*
* Evaluates to non-zero if the argument is a letter.
*/
#define is_letter(ch) \
(is_upper(ch) || is_lower(ch))
/*
* Evaluates to non-zero if the argument is a linear whitespace character.
* For the purposes of this macro, the definition of linear whitespace is
* extended to include the form feed and carraige return characters.
*/
#define is_lws(ch) \
(ch == ' ' || ch == '\t' || ch == '\f' || ch == '\r')
/*
* Evaluates to non-zero if the argument is a whitespace character.
*/
#define is_ws(ch) \
(is_lws(ch) || ch == '\n')
/*
* Evaluates to non-zero if the argument is a printable ASCII character.
* Assumes that the execution character set is a superset of ASCII.
*/
#define is_p(ch) \
(ch >= '!' && ch <= '~')
/*
* Evaluates to non-zero if the argument belongs to the POSIX Portable
* Filename Character Set. Assumes that the execution character set is a
* superset of ASCII.
*/
#define is_pfcs(ch) \
(is_digit(ch) || is_letter(ch) || \
ch == '.' || ch == '_' || ch == '-')
/*
* Evaluates to non-zero if the argument is an unreserved character
* according to RFC 3986, i.e. can be used unencoded in URIs.
*/
#define is_uri(ch) \
(is_digit(ch) || is_letter(ch) || \
ch == '.' || ch == '_' || ch == '-' || ch == '~')
#endif

85
include/cryb/digest.h Normal file
View file

@ -0,0 +1,85 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#ifndef CRYB_DIGEST_H_INCLUDED
#define CRYB_DIGEST_H_INCLUDED
typedef void *(*digest_init_func)(void);
typedef void (*digest_update_func)(void *, const void *, size_t);
typedef void (*digest_final_func)(void *, void *);
typedef int (*digest_complete_func)(const void *, size_t, void *);
struct digest_algorithm {
const char *name; /* algorithm name */
size_t ctxsize; /* size of context structure */
size_t resultlen; /* length of the result */
digest_init_func init;
digest_update_func update;
digest_final_func final;
digest_complete_func complete;
};
const struct digest_algorithm *cryb_digest_algorithm(const char *);
void *cryb_digest_init(const char *);
void cryb_digest_update(void *, const void *, size_t);
void cryb_digest_final(void *, void *);
int cryb_digest_complete(const char *, const void *, size_t, void *);
static inline void *
digest_init(const char *alg)
{
return (cryb_digest_init(alg));
}
static inline void
digest_update(void *ctx, const void *msg, size_t msglen)
{
cryb_digest_update(ctx, msg, msglen);
}
static inline void
digest_final(void *ctx, void *md)
{
cryb_digest_final(ctx, md);
}
static inline int
digest_complete(const char *alg, const void *msg, size_t msglen, void *md)
{
return (cryb_digest_complete(alg, msg, msglen, md));
}
#endif

53
include/cryb/hmac.h Normal file
View file

@ -0,0 +1,53 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#ifndef CRYB_HMAC_H_INCLUDED
#define CRYB_HMAC_H_INCLUDED
#define HMAC_LEN 20
typedef struct hmac_ctx {
struct sha1_ctx sha1_ctx;
uint8_t key[64];
size_t keylen;
} hmac_ctx;
void hmac_init(hmac_ctx *, const uint8_t *, size_t);
void hmac_update(hmac_ctx *, const uint8_t *, size_t);
void hmac_final(hmac_ctx *, uint8_t *);
void hmac_complete(const uint8_t *, size_t, const uint8_t *, size_t, uint8_t *);
#endif

39
include/cryb/hotp.h Normal file
View file

@ -0,0 +1,39 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#ifndef CRYB_HOTP_H_INCLUDED
#define CRYB_HOTP_H_INCLUDED
#endif

44
include/cryb/impl.h Normal file
View file

@ -0,0 +1,44 @@
/*-
* Copyright (c) 2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#ifndef CRYB_IMPL_H_INCLUDED
#define CRYB_IMPL_H_INCLUDED
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "cryb/attributes.h"
#include "cryb/coverage.h"
#endif

39
include/cryb/mac.h Normal file
View file

@ -0,0 +1,39 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#ifndef CRYB_MAC_H_INCLUDED
#define CRYB_MAC_H_INCLUDED
#endif

57
include/cryb/md5.h Normal file
View file

@ -0,0 +1,57 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#ifndef CRYB_MD5_H_INCLUDED
#define CRYB_MD5_H_INCLUDED
#define MD5_DIGEST_LEN 16
typedef struct md5_ctx {
uint8_t block[64];
size_t blocklen;
uint64_t bitlen;
uint32_t h[4];
} md5_ctx;
#define md5_init cryb_md5_init
#define md5_update cryb_md5_update
#define md5_final cryb_md5_final
#define md5_complete cryb_md5_complete
void md5_init(md5_ctx *);
void md5_update(md5_ctx *, const void *, size_t);
void md5_final(md5_ctx *, void *);
void md5_complete(const void *, size_t, void *);
#endif

60
include/cryb/oath.h Normal file
View file

@ -0,0 +1,60 @@
/*-
* Copyright (c) 2012-2014 Universitetet i Oslo
* Copyright (c) 2013-2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#ifndef OATH_H_INCLUDED
#define OATH_H_INCLUDED
#include <cryb/oath_constants.h>
#include <cryb/oath_types.h>
struct oath_key *oath_key_alloc(void);
struct oath_key *oath_key_create(const char *, enum oath_mode,
enum oath_hash, const char *, size_t);
void oath_key_free(struct oath_key *);
struct oath_key *oath_key_from_uri(const char *);
struct oath_key *oath_key_from_file(const char *);
char *oath_key_to_uri(const struct oath_key *);
struct oath_key *oath_key_dummy(enum oath_mode, enum oath_hash, unsigned int);
unsigned int oath_hotp(const uint8_t *, size_t, uint64_t, unsigned int);
unsigned int oath_hotp_current(struct oath_key *);
int oath_hotp_match(struct oath_key *, unsigned int, int);
unsigned int oath_totp(const uint8_t *, size_t, unsigned int);
unsigned int oath_totp_current(const struct oath_key *);
int oath_totp_match(struct oath_key *, unsigned int, int);
#endif

View file

@ -0,0 +1,88 @@
/*-
* Copyright (c) 2012-2013 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#ifndef OATH_CONSTANTS_H_INCLUDED
#define OATH_CONSTANTS_H_INCLUDED
/*
* OATH modes
*/
enum oath_mode {
om_undef, /* not set / default */
om_hotp, /* RFC 4226 HOTP */
om_totp, /* RFC 6238 TOTP */
om_ocra, /* RFC 6287 OCRA */
om_max
};
/*
* Hash functions
*/
enum oath_hash {
oh_undef, /* not set / default */
oh_md5, /* RFC 1321 MD5 */
oh_sha1, /* FIPS 180 SHA-1 */
oh_sha256, /* FIPS 180 SHA-256 */
oh_sha512, /* FIPS 180 SHA-512 */
oh_max
};
/*
* Default time step for TOTP: 30 seconds.
*/
#define OATH_DEF_TIMESTEP 30
/*
* Maximum time step for TOTP: 10 minutes, which RFC 6238 cites as an
* example of an unreasonably large time step.
*/
#define OATH_MAX_TIMESTEP 600
/*
* Maximum key length in bytes. HMAC has a 64-byte block size; if the key
* K is longer than that, HMAC derives a new key K' = H(K).
*/
#define OATH_MAX_KEYLEN 64
/*
* Maximum label length in characters, including terminating NUL.
*/
#define OATH_MAX_LABELLEN 64
/*
* Label to use for dummy keys
*/
#define OATH_DUMMY_LABEL "oath-dummy@openpam.org"
#endif

66
include/cryb/oath_types.h Normal file
View file

@ -0,0 +1,66 @@
/*-
* Copyright (c) 2012-2013 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#ifndef OATH_TYPES_H_INCLUDED
#define OATH_TYPES_H_INCLUDED
/*
* OATH key and associated parameters
*/
struct oath_key {
/* mode and parameters */
enum oath_mode mode;
unsigned int digits;
uint64_t counter; /* HOTP only */
unsigned int timestep; /* TOTP only - in seconds */
uint64_t lastused; /* TOTP only */
/* housekeeping */
unsigned int dummy:1; /* dummy key, always fail */
unsigned int mapped:1; /* allocated with mmap() */
unsigned int locked:1; /* locked / wired with madvise() */
/* hash algorithm */
enum oath_hash hash;
/* label */
size_t labellen; /* bytes incl. NUL */
char label[OATH_MAX_LABELLEN];
/* key */
size_t keylen; /* bytes */
uint8_t key[OATH_MAX_KEYLEN];
};
#endif

40
include/cryb/rand.h Normal file
View file

@ -0,0 +1,40 @@
/*-
* Copyright (c) 2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#ifndef CRYB_RAND_H_INCLUDED
#define CRYB_RAND_H_INCLUDED
#define rand_bytes cryb_rand_bytes
int rand_bytes(uint8_t *, size_t);
#endif

46
include/cryb/rfc3986.h Normal file
View file

@ -0,0 +1,46 @@
/*-
* Copyright (c) 2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#ifndef CRYB_RFC3986_H_INCLUDED
#define CRYB_RFC3986_H_INCLUDED
/* estimate of output length for percent encoding / decoding */
#define percent_enclen(l) (size_t)((l) * 3)
#define percent_declen(l) (size_t)(l)
#define percent_encode cryb_percent_encode
#define percent_decode cryb_percent_decode
int percent_encode(const char *, size_t, char *, size_t *);
int percent_decode(const char *, size_t, char *, size_t *);
#endif

58
include/cryb/rfc4648.h Normal file
View file

@ -0,0 +1,58 @@
/*-
* Copyright (c) 2012-2013 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#ifndef CRYB_RFC4648_H_INCLUDED
#define CRYB_RFC4648_H_INCLUDED
/* estimate of output length for base32 encoding / decoding */
#define base32_enclen(l) (size_t)(((l + 4) / 5) * 8)
#define base32_declen(l) (size_t)(((l + 7) / 8) * 5)
/* base32 encoding / decoding */
#define base32_encode cryb_base32_encode
#define base32_decode cryb_base32_decode
int base32_encode(const uint8_t *, size_t, char *, size_t *);
int base32_decode(const char *, size_t, uint8_t *, size_t *);
/* estimate of output length for base64 encoding / decoding */
#define base64_enclen(l) (size_t)(((l + 2) / 3) * 4)
#define base64_declen(l) (size_t)(((l + 3) / 4) * 3)
/* base64 encoding / decoding */
#define base64_encode cryb_base64_encode
#define base64_decode cryb_base64_decode
int base64_encode(const uint8_t *, size_t, char *, size_t *);
int base64_decode(const char *, size_t, uint8_t *, size_t *);
#endif

57
include/cryb/sha1.h Normal file
View file

@ -0,0 +1,57 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#ifndef CRYB_SHA1_H_INCLUDED
#define CRYB_SHA1_H_INCLUDED
#define SHA1_DIGEST_LEN 20
typedef struct sha1_ctx {
uint8_t block[64];
size_t blocklen;
uint64_t bitlen;
uint32_t h[5], k[4];
} sha1_ctx;
#define sha1_init cryb_sha1_init
#define sha1_update cryb_sha1_update
#define sha1_final cryb_sha1_final
#define sha1_complete cryb_sha1_complete
void sha1_init(sha1_ctx *);
void sha1_update(sha1_ctx *, const void *, size_t);
void sha1_final(sha1_ctx *, void *);
void sha1_complete(const void *, size_t, void *);
#endif

43
include/cryb/strlcat.h Normal file
View file

@ -0,0 +1,43 @@
/*-
* Copyright (c) 2011 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#ifndef OPENPAM_STRLCAT_H_INCLUDED
#define OPENPAM_STRLCAT_H_INCLUDED
#ifndef HAVE_STRLCAT
size_t cryb_strlcat(char *, const char *, size_t);
#undef strlcat
#define strlcat(arg, ...) cryb_strlcat(arg, __VA_ARGS__)
#endif
#endif

43
include/cryb/strlcmp.h Normal file
View file

@ -0,0 +1,43 @@
/*-
* Copyright (c) 2011 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#ifndef CRYB_STRLCMP_H_INCLUDED
#define CRYB_STRLCMP_H_INCLUDED
#ifndef HAVE_STRLCMP
int cryb_strlcmp(const char *, const char *, size_t);
#undef strlcmp
#define strlcmp(...) cryb_strlcmp(__VA_ARGS__)
#endif
#endif

43
include/cryb/strlcpy.h Normal file
View file

@ -0,0 +1,43 @@
/*-
* Copyright (c) 2011 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#ifndef OPENPAM_STRLCPY_H_INCLUDED
#define OPENPAM_STRLCPY_H_INCLUDED
#ifndef HAVE_STRLCPY
size_t cryb_strlcpy(char *, const char *, size_t);
#undef strlcpy
#define strlcpy(arg, ...) cryb_strlcpy(arg, __VA_ARGS__)
#endif
#endif

37
include/cryb/to.h Normal file
View file

@ -0,0 +1,37 @@
/*-
* Copyright (c) 2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#ifndef CRYB_TO_H_INCLUDED
#define CRYB_TO_H_INCLUDED
#endif

39
include/cryb/totp.h Normal file
View file

@ -0,0 +1,39 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#ifndef CRYB_TOTP_H_INCLUDED
#define CRYB_TOTP_H_INCLUDED
#endif

39
include/cryb/version.h Normal file
View file

@ -0,0 +1,39 @@
/*-
* Copyright (c) 2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#ifndef CRYB_VERSION_H_INCLUDED
#define CRYB_VERSION_H_INCLUDED
#define CRYB_VERSION 20140311
#endif

13
lib/Makefile.am Normal file
View file

@ -0,0 +1,13 @@
# $Id$
SUBDIRS = \
core \
digest \
enc \
mac \
rand \
oath
if WITH_RSAREF
SUBDIRS += rsaref
endif

11
lib/core/Makefile.am Normal file
View file

@ -0,0 +1,11 @@
# $Id$
AM_CPPFLAGS = -I$(top_srcdir)/include
lib_LTLIBRARIES = libcryb-core.la
libcryb_core_la_SOURCES = \
cryb_core.c \
cryb_strlcat.c \
cryb_strlcpy.c \
cryb_strlcmp.c

36
lib/core/cryb_core.c Normal file
View file

@ -0,0 +1,36 @@
/*-
* Copyright (c) 2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#include "cryb/impl.h"
#include <cryb/to.h>

54
lib/core/cryb_strlcat.c Normal file
View file

@ -0,0 +1,54 @@
/*-
* Copyright (c) 2011-2012 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#include "cryb/impl.h"
#include <stddef.h>
#include <cryb/strlcat.h>
/* like strcat(3), but always NUL-terminates; returns strlen(src) */
size_t
cryb_strlcat(char *dst, const char *src, size_t size)
{
size_t len;
for (len = 0; *dst && size > 1; ++len, --size)
dst++;
for (; *src && size > 1; ++len, --size)
*dst++ = *src++;
*dst = '\0';
while (*src)
++len, ++src;
return (len);
}

49
lib/core/cryb_strlcmp.c Normal file
View file

@ -0,0 +1,49 @@
/*-
* Copyright (c) 2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#include "cryb/impl.h"
#include <stddef.h>
#include <cryb/strlcmp.h>
/* like strcmp, but only compares up to len characters */
int
cryb_strlcmp(const char *s1, const char *s2, size_t len)
{
for (; len && *s1 && *s2; --len, ++s1, ++s2)
if (*s1 != *s2)
return ((unsigned char)*s1 - (unsigned char)*s2);
return ((unsigned char)*s1);
}

52
lib/core/cryb_strlcpy.c Normal file
View file

@ -0,0 +1,52 @@
/*-
* Copyright (c) 2011-2012 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#include "cryb/impl.h"
#include <stddef.h>
#include <cryb/strlcpy.h>
/* like strcpy(3), but always NUL-terminates; returns strlen(src) */
size_t
cryb_strlcpy(char *dst, const char *src, size_t size)
{
size_t len;
for (len = 0; *src && size > 1; ++len, --size)
*dst++ = *src++;
*dst = '\0';
while (*src)
++len, ++src;
return (len);
}

9
lib/digest/Makefile.am Normal file
View file

@ -0,0 +1,9 @@
# $Id$
AM_CPPFLAGS = -I$(top_srcdir)/include
lib_LTLIBRARIES = libcryb-digest.la
libcryb_digest_la_SOURCES = \
md5.c \
sha1.c

69
lib/digest/digest.c Normal file
View file

@ -0,0 +1,69 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <string.h>
#include <cryb/digest.h>
#include <cryb/md5.h>
#include <cryb/sha1.h>
static const struct digest_algorithm **cryb_digest_algorithms;
static void
cryb_init_digest_algorithms(void)
{
static const struct digest_algorithm *algorithms[] = {
&cryb_md5_algorithm,
&cryb_sha1_algorithm,
NULL
};
cryb_digest_algorithms = algorithms;
}
const struct digest_algorithm *
cryb_digest_algorithm(const char *name)
{
const struct digest_algorithm **algp;
if (cryb_digest_algorithms == NULL)
cryb_init_digest_algorithms();
for (algp = cryb_digest_algorithms; *algp != NULL; ++algp)
if (strcasecmp((*algp)->name, name) == 0)
return (*algp);
return (NULL);
}

261
lib/digest/md5.c Normal file
View file

@ -0,0 +1,261 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012-2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_ENDIAN_H
#include <sys/endian.h>
#endif
#ifdef HAVE_ENDIAN_H
#define _BSD_SOURCE
#include <endian.h>
#endif
#include <cryb/digest.h>
#include <cryb/bitwise.h>
#include <cryb/md5.h>
/* initial state */
static const uint32_t md5_h[4] = {
0x67452301U, 0xefcdab89U, 0x98badcfeU, 0x10325476U,
};
static const uint32_t md5_k[64] = {
0xd76aa478U, 0xe8c7b756U, 0x242070dbU, 0xc1bdceeeU,
0xf57c0fafU, 0x4787c62aU, 0xa8304613U, 0xfd469501U,
0x698098d8U, 0x8b44f7afU, 0xffff5bb1U, 0x895cd7beU,
0x6b901122U, 0xfd987193U, 0xa679438eU, 0x49b40821U,
0xf61e2562U, 0xc040b340U, 0x265e5a51U, 0xe9b6c7aaU,
0xd62f105dU, 0x02441453U, 0xd8a1e681U, 0xe7d3fbc8U,
0x21e1cde6U, 0xc33707d6U, 0xf4d50d87U, 0x455a14edU,
0xa9e3e905U, 0xfcefa3f8U, 0x676f02d9U, 0x8d2a4c8aU,
0xfffa3942U, 0x8771f681U, 0x6d9d6122U, 0xfde5380cU,
0xa4beea44U, 0x4bdecfa9U, 0xf6bb4b60U, 0xbebfbc70U,
0x289b7ec6U, 0xeaa127faU, 0xd4ef3085U, 0x04881d05U,
0xd9d4d039U, 0xe6db99e5U, 0x1fa27cf8U, 0xc4ac5665U,
0xf4292244U, 0x432aff97U, 0xab9423a7U, 0xfc93a039U,
0x655b59c3U, 0x8f0ccc92U, 0xffeff47dU, 0x85845dd1U,
0x6fa87e4fU, 0xfe2ce6e0U, 0xa3014314U, 0x4e0811a1U,
0xf7537e82U, 0xbd3af235U, 0x2ad7d2bbU, 0xeb86d391U,
};
void
md5_init(struct md5_ctx *ctx)
{
memset(ctx, 0, sizeof *ctx);
memcpy(ctx->h, md5_h, sizeof ctx->h);
}
#define md5_f(i, a, b, c, d, x, s) do { \
(a) += (((b) & (c)) | (~(b) & (d))); \
(a) += (x)[(i)] + md5_k[(i)]; \
(a) = rol((a), (s)) + (b); \
++(i); \
} while (0)
#define md5_g(i, a, b, c, d, x, s) do { \
(a) += (((b) & (d)) | ((c) & ~(d))); \
(a) += (x)[(5 * (i) + 1) % 16] + md5_k[(i)]; \
(a) = rol((a), (s)) + (b); \
++(i); \
} while (0)
#define md5_h(i, a, b, c, d, x, s) do { \
(a) += ((b) ^ (c) ^ (d)); \
(a) += (x)[(3 * (i) + 5) % 16] + md5_k[(i)]; \
(a) = rol((a), (s)) + (b); \
++(i); \
} while (0)
#define md5_i(i, a, b, c, d, x, s) do { \
(a) += ((c) ^ ((b) | ~(d))); \
(a) += (x)[(7 * (i)) % 16] + md5_k[(i)]; \
(a) = rol((a), (s)) + (b); \
++(i); \
} while (0)
static void
md5_compute(struct md5_ctx *ctx, const uint8_t *block)
{
uint32_t w[16], a, b, c, d;
int i;
memcpy(w, block, 64);
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
w[i] = le32toh(w[i]);
#endif
a = ctx->h[0];
b = ctx->h[1];
c = ctx->h[2];
d = ctx->h[3];
i = 0;
md5_f(i, a, b, c, d, w, 7);
md5_f(i, d, a, b, c, w, 12);
md5_f(i, c, d, a, b, w, 17);
md5_f(i, b, c, d, a, w, 22);
md5_f(i, a, b, c, d, w, 7);
md5_f(i, d, a, b, c, w, 12);
md5_f(i, c, d, a, b, w, 17);
md5_f(i, b, c, d, a, w, 22);
md5_f(i, a, b, c, d, w, 7);
md5_f(i, d, a, b, c, w, 12);
md5_f(i, c, d, a, b, w, 17);
md5_f(i, b, c, d, a, w, 22);
md5_f(i, a, b, c, d, w, 7);
md5_f(i, d, a, b, c, w, 12);
md5_f(i, c, d, a, b, w, 17);
md5_f(i, b, c, d, a, w, 22);
md5_g(i, a, b, c, d, w, 5);
md5_g(i, d, a, b, c, w, 9);
md5_g(i, c, d, a, b, w, 14);
md5_g(i, b, c, d, a, w, 20);
md5_g(i, a, b, c, d, w, 5);
md5_g(i, d, a, b, c, w, 9);
md5_g(i, c, d, a, b, w, 14);
md5_g(i, b, c, d, a, w, 20);
md5_g(i, a, b, c, d, w, 5);
md5_g(i, d, a, b, c, w, 9);
md5_g(i, c, d, a, b, w, 14);
md5_g(i, b, c, d, a, w, 20);
md5_g(i, a, b, c, d, w, 5);
md5_g(i, d, a, b, c, w, 9);
md5_g(i, c, d, a, b, w, 14);
md5_g(i, b, c, d, a, w, 20);
md5_h(i, a, b, c, d, w, 4);
md5_h(i, d, a, b, c, w, 11);
md5_h(i, c, d, a, b, w, 16);
md5_h(i, b, c, d, a, w, 23);
md5_h(i, a, b, c, d, w, 4);
md5_h(i, d, a, b, c, w, 11);
md5_h(i, c, d, a, b, w, 16);
md5_h(i, b, c, d, a, w, 23);
md5_h(i, a, b, c, d, w, 4);
md5_h(i, d, a, b, c, w, 11);
md5_h(i, c, d, a, b, w, 16);
md5_h(i, b, c, d, a, w, 23);
md5_h(i, a, b, c, d, w, 4);
md5_h(i, d, a, b, c, w, 11);
md5_h(i, c, d, a, b, w, 16);
md5_h(i, b, c, d, a, w, 23);
md5_i(i, a, b, c, d, w, 6);
md5_i(i, d, a, b, c, w, 10);
md5_i(i, c, d, a, b, w, 15);
md5_i(i, b, c, d, a, w, 21);
md5_i(i, a, b, c, d, w, 6);
md5_i(i, d, a, b, c, w, 10);
md5_i(i, c, d, a, b, w, 15);
md5_i(i, b, c, d, a, w, 21);
md5_i(i, a, b, c, d, w, 6);
md5_i(i, d, a, b, c, w, 10);
md5_i(i, c, d, a, b, w, 15);
md5_i(i, b, c, d, a, w, 21);
md5_i(i, a, b, c, d, w, 6);
md5_i(i, d, a, b, c, w, 10);
md5_i(i, c, d, a, b, w, 15);
md5_i(i, b, c, d, a, w, 21);
ctx->h[0] += a;
ctx->h[1] += b;
ctx->h[2] += c;
ctx->h[3] += d;
}
void
md5_update(struct md5_ctx *ctx, const void *buf, size_t len)
{
size_t copylen;
while (len) {
if (ctx->blocklen > 0 || len < 64) {
copylen = 64 - ctx->blocklen;
if (copylen > len)
copylen = len;
memcpy(ctx->block + ctx->blocklen, buf, copylen);
ctx->blocklen += copylen;
if (ctx->blocklen == 64) {
md5_compute(ctx, ctx->block);
ctx->blocklen = 0;
memset(ctx->block, 0, 64);
}
} else {
copylen = 64;
md5_compute(ctx, buf);
}
ctx->bitlen += copylen * 8;
buf += copylen;
len -= copylen;
}
}
void
md5_final(struct md5_ctx *ctx, void *digest)
{
ctx->block[ctx->blocklen++] = 0x80;
if (ctx->blocklen > 56) {
md5_compute(ctx, ctx->block);
ctx->blocklen = 0;
memset(ctx->block, 0, 64);
}
le32enc(ctx->block + 56, ctx->bitlen & 0xffffffffUL);
le32enc(ctx->block + 60, ctx->bitlen >> 32);
md5_compute(ctx, ctx->block);
le32enc(digest, ctx->h[0]);
le32enc(digest + 4, ctx->h[1]);
le32enc(digest + 8, ctx->h[2]);
le32enc(digest + 12, ctx->h[3]);
memset(ctx, 0, sizeof *ctx);
}
void
md5_complete(const void *buf, size_t len, void *digest)
{
struct md5_ctx ctx;
md5_init(&ctx);
md5_update(&ctx, buf, len);
md5_final(&ctx, digest);
}

173
lib/digest/sha1.c Normal file
View file

@ -0,0 +1,173 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012-2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_ENDIAN_H
#include <sys/endian.h>
#endif
#ifdef HAVE_ENDIAN_H
#define _BSD_SOURCE
#include <endian.h>
#endif
#include <cryb/digest.h>
#include <cryb/bitwise.h>
#include <cryb/sha1.h>
static uint32_t sha1_h[5] = {
0x67452301U, 0xefcdab89U, 0x98badcfeU, 0x10325476U, 0xc3d2e1f0U,
};
static uint32_t sha1_k[4] = {
0x5a827999U, 0x6ed9eba1U, 0x8f1bbcdcU, 0xca62c1d6U,
};
void
sha1_init(struct sha1_ctx *ctx)
{
memset(ctx, 0, sizeof *ctx);
memcpy(ctx->h, sha1_h, sizeof ctx->h);
memcpy(ctx->k, sha1_k, sizeof ctx->k);
}
static void
sha1_compute(struct sha1_ctx *ctx, const uint8_t *block)
{
uint32_t w[80], a, b, c, d, e, f, temp;
memcpy(w, block, 64);
#if !WORDS_BIGENDIAN
for (int i = 0; i < 16; ++i)
w[i] = be32toh(w[i]);
#endif
for (int i = 16; i < 80; ++i) {
w[i] = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
w[i] = rol(w[i], 1);
}
a = ctx->h[0];
b = ctx->h[1];
c = ctx->h[2];
d = ctx->h[3];
e = ctx->h[4];
for (int t = 0; t < 80; ++t) {
if (t < 20)
f = (b & c) | ((~b) & d);
else if (t < 40)
f = b ^ c ^ d;
else if (t < 60)
f = (b & c) | (b & d) | (c & d);
else
f = b ^ c ^ d;
temp = rol(a, 5) + f + e + w[t] + ctx->k[t/20];
e = d;
d = c;
c = ror(b, 2);
b = a;
a = temp;
}
ctx->h[0] += a;
ctx->h[1] += b;
ctx->h[2] += c;
ctx->h[3] += d;
ctx->h[4] += e;
}
void
sha1_update(struct sha1_ctx *ctx, const void *buf, size_t len)
{
size_t copylen;
while (len) {
if (ctx->blocklen > 0 || len < 64) {
copylen = sizeof ctx->block - ctx->blocklen;
if (copylen > len)
copylen = len;
memcpy(ctx->block + ctx->blocklen, buf, copylen);
ctx->blocklen += copylen;
if (ctx->blocklen == 64) {
sha1_compute(ctx, ctx->block);
ctx->blocklen = 0;
memset(ctx->block, 0, 64);
}
} else {
copylen = 64;
sha1_compute(ctx, buf);
}
ctx->bitlen += copylen * 8;
buf += copylen;
len -= copylen;
}
}
void
sha1_final(struct sha1_ctx *ctx, void *digest)
{
uint32_t hi, lo;
ctx->block[ctx->blocklen++] = 0x80;
if (ctx->blocklen > 56) {
sha1_compute(ctx, ctx->block);
ctx->blocklen = 0;
memset(ctx->block, 0, 64);
}
hi = htobe32(ctx->bitlen >> 32);
lo = htobe32(ctx->bitlen & 0xffffffffUL);
memcpy(ctx->block + 56, &hi, 4);
memcpy(ctx->block + 60, &lo, 4);
ctx->blocklen = 64;
sha1_compute(ctx, ctx->block);
for (int i = 0; i < 5; ++i)
ctx->h[i] = htobe32(ctx->h[i]);
memcpy(digest, ctx->h, 20);
memset(ctx, 0, sizeof *ctx);
}
void
sha1_complete(const void *buf, size_t len, void *digest)
{
struct sha1_ctx ctx;
sha1_init(&ctx);
sha1_update(&ctx, buf, len);
sha1_final(&ctx, digest);
}

10
lib/enc/Makefile.am Normal file
View file

@ -0,0 +1,10 @@
# $Id$
AM_CPPFLAGS = -I$(top_srcdir)/include
lib_LTLIBRARIES = libcryb-enc.la
libcryb_enc_la_SOURCES = \
cryb_base32.c \
cryb_base64.c \
cryb_percent.c

201
lib/enc/cryb_base32.c Normal file
View file

@ -0,0 +1,201 @@
/*-
* Copyright (c) 2013-2014 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <sys/types.h>
#include <errno.h>
#include <stdint.h>
#include <cryb/rfc4648.h>
static const char b32enc[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
static const char b32dec[256] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
/*
* Encode data in RFC 4648 base 32 representation. The target buffer must
* have room for base32_enclen(len) characters and a terminating NUL.
*/
int
base32_encode(const uint8_t *in, size_t ilen, char *out, size_t *olen)
{
uint64_t bits;
if (*olen <= base32_enclen(ilen)) {
*olen = base32_enclen(ilen) + 1;
errno = ENOSPC;
return (-1);
}
*olen = base32_enclen(ilen) + 1;
while (ilen >= 5) {
bits = 0;
bits |= (uint64_t)*in++ << 32;
bits |= (uint64_t)*in++ << 24;
bits |= (uint64_t)*in++ << 16;
bits |= (uint64_t)*in++ << 8;
bits |= (uint64_t)*in++;
*out++ = b32enc[bits >> 35 & 0x1f];
*out++ = b32enc[bits >> 30 & 0x1f];
*out++ = b32enc[bits >> 25 & 0x1f];
*out++ = b32enc[bits >> 20 & 0x1f];
*out++ = b32enc[bits >> 15 & 0x1f];
*out++ = b32enc[bits >> 10 & 0x1f];
*out++ = b32enc[bits >> 5 & 0x1f];
*out++ = b32enc[bits & 0x1f];
ilen -= 5;
}
if (ilen > 0) {
bits = 0;
switch (ilen) {
case 4:
bits |= (uint64_t)in[3] << 8;
case 3:
bits |= (uint64_t)in[2] << 16;
case 2:
bits |= (uint64_t)in[1] << 24;
case 1:
bits |= (uint64_t)in[0] << 32;
CRYB_NO_DEFAULT_CASE
}
*out++ = b32enc[bits >> 35 & 0x1f];
*out++ = b32enc[bits >> 30 & 0x1f];
*out++ = ilen > 1 ? b32enc[bits >> 25 & 0x1f] : '=';
*out++ = ilen > 1 ? b32enc[bits >> 20 & 0x1f] : '=';
*out++ = ilen > 2 ? b32enc[bits >> 15 & 0x1f] : '=';
*out++ = ilen > 3 ? b32enc[bits >> 10 & 0x1f] : '=';
*out++ = ilen > 3 ? b32enc[bits >> 5 & 0x1f] : '=';
*out++ = '=';
}
*out++ = '\0';
return (0);
}
/*
* Decode data in RFC 4648 base 32 representation, stopping at the
* terminating NUL, the first invalid (non-base32, non-whitespace)
* character or after len characters, whichever comes first.
*
* Padding is handled sloppily: any padding character following the data
* is silently consumed. This not only simplifies the code but ensures
* compatibility with implementations which do not emit or understand
* padding.
*
* The olen argument is used by the caller to pass the size of the buffer
* and by base32_decode() to return the amount of data successfully
* decoded. If the buffer is too small, base32_decode() discards the
* excess data, but returns the total amount.
*/
int
base32_decode(const char *in, size_t ilen, uint8_t *out, size_t *olen)
{
size_t len;
int bits, shift, padding;
for (bits = shift = padding = len = 0; ilen && *in; --ilen, ++in) {
if (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n' ||
(padding && *in == '=')) {
/* consume */
continue;
} else if (!padding && b32dec[(uint8_t)*in] >= 0) {
/* shift into accumulator */
shift += 5;
bits = bits << 5 | b32dec[(uint8_t)*in];
} else if (!padding && *in == '=' &&
(shift == 1 || shift == 2 || shift == 3 || shift == 4)) {
/* final byte */
padding = 1;
} else {
/* error */
*olen = 0;
errno = EINVAL;
return (-1);
}
if (shift >= 8) {
/* output accumulated byte */
shift -= 8;
if (len++ < *olen)
*out++ = (bits >> shift) & 0xff;
}
}
/* non-zero bits in last byte before padding */
if (shift && (bits & ~(~0 << shift)) != 0) {
errno = EINVAL;
return (-1);
}
/* report decoded length */
if (len > *olen) {
/* overflow */
*olen = len;
errno = ENOSPC;
return (-1);
}
*olen = len;
return (0);
}

189
lib/enc/cryb_base64.c Normal file
View file

@ -0,0 +1,189 @@
/*-
* Copyright (c) 2013-2014 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <sys/types.h>
#include <errno.h>
#include <stdint.h>
#include <cryb/rfc4648.h>
static const char b64enc[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static const char b64dec[256] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
/*
* Encode data in RFC 4648 base 64 representation. The target buffer must
* have room for base64_enclen(len) characters and a terminating NUL.
*/
int
base64_encode(const uint8_t *in, size_t ilen, char *out, size_t *olen)
{
uint32_t bits;
if (*olen <= base64_enclen(ilen)) {
*olen = base64_enclen(ilen) + 1;
errno = ENOSPC;
return (-1);
}
*olen = base64_enclen(ilen) + 1;
while (ilen >= 3) {
bits = 0;
bits |= (uint32_t)*in++ << 16;
bits |= (uint32_t)*in++ << 8;
bits |= (uint32_t)*in++;
ilen -= 3;
*out++ = b64enc[bits >> 18 & 0x3f];
*out++ = b64enc[bits >> 12 & 0x3f];
*out++ = b64enc[bits >> 6 & 0x3f];
*out++ = b64enc[bits & 0x3f];
}
if (ilen > 0) {
bits = 0;
switch (ilen) {
case 2:
bits |= (uint32_t)in[1] << 8;
case 1:
bits |= (uint32_t)in[0] << 16;
CRYB_NO_DEFAULT_CASE
}
*out++ = b64enc[bits >> 18 & 0x3f];
*out++ = b64enc[bits >> 12 & 0x3f];
*out++ = ilen > 1 ? b64enc[bits >> 6 & 0x3f] : '=';
*out++ = '=';
}
*out++ = '\0';
return (0);
}
/*
* Decode data in RFC 4648 base 64 representation, stopping at the
* terminating NUL, the first invalid (non-base64, non-whitespace)
* character or after len characters, whichever comes first.
*
* Padding is handled sloppily: any padding character following the data
* is silently consumed. This not only simplifies the code but ensures
* compatibility with implementations which do not emit or understand
* padding.
*
* The olen argument is used by the caller to pass the size of the buffer
* and by base64_decode() to return the amount of data successfully
* decoded. If the buffer is too small, base64_decode() discards the
* excess data, but returns the total amount.
*/
int
base64_decode(const char *in, size_t ilen, uint8_t *out, size_t *olen)
{
size_t len;
int bits, shift, padding;
for (bits = shift = padding = len = 0; ilen && *in; --ilen, ++in) {
if (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n' ||
(padding && *in == '=')) {
/* consume */
continue;
} else if (!padding && b64dec[(uint8_t)*in] >= 0) {
/* shift into accumulator */
shift += 6;
bits = bits << 6 | b64dec[(uint8_t)*in];
} else if (!padding && *in == '=' &&
(shift == 2 || shift == 4)) {
/* final byte */
padding = 1;
} else {
/* error */
*olen = 0;
errno = EINVAL;
return (-1);
}
if (shift >= 8) {
/* output accumulated byte */
shift -= 8;
if (len++ < *olen)
*out++ = (bits >> shift) & 0xff;
}
}
/* non-zero bits in last byte before padding */
if (shift && (bits & ~(~0 << shift)) != 0) {
errno = EINVAL;
return (-1);
}
/* report decoded length */
if (len > *olen) {
/* overflow */
*olen = len;
errno = ENOSPC;
return (-1);
}
*olen = len;
return (0);
}

115
lib/enc/cryb_percent.c Normal file
View file

@ -0,0 +1,115 @@
/*-
* Copyright (c) 2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#include "cryb/impl.h"
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <cryb/ctype.h>
#include <cryb/rfc3986.h>
static const char hex[] = "0123456789ABCDEF";
#define unhex(ch) \
((ch >= '0' && ch <= '9') ? ch - '0' : \
(ch >= 'A' && ch <= 'F') ? 0xa + ch - 'A' : \
(ch >= 'a' && ch <= 'f') ? 0xa + ch - 'a' : 0)
/*
* Encodes a string in RFC 3986 percent-encoded representation.
*/
int
percent_encode(const char *in, size_t ilen, char *out, size_t *olen)
{
size_t len;
for (len = 0; ilen && *in; --ilen, ++in) {
if (is_uri(*in)) {
if (len++ < *olen)
*out++ = *in;
} else {
if (len++ < *olen)
*out++ = '%';
if (len++ < *olen)
*out++ = hex[(uint8_t)*in >> 4];
if (len++ < *olen)
*out++ = hex[(uint8_t)*in & 0xf];
}
}
if (len < *olen)
*out = '\0';
if (len >= *olen) {
/* overflow */
*olen = len;
errno = ENOSPC;
return (-1);
}
*olen = len;
return (0);
}
/*
* Decodes a string in RFC 3986 percent-encoded representation.
*/
int
percent_decode(const char *in, size_t ilen, char *out, size_t *olen)
{
size_t len;
for (len = 0; ilen && *in; --ilen, ++in) {
if (*in != '%') {
if (++len < *olen)
*out++ = *in;
} else if (ilen >= 3 && is_xdigit(in[1]) && is_xdigit(in[2])) {
if (++len < *olen)
*out++ = unhex(in[1]) << 4 | unhex(in[2]);
in += 2;
} else {
errno = EINVAL;
return (-1);
}
}
if (len < *olen)
*out = '\0';
if (len >= *olen) {
/* overflow */
*olen = len;
errno = ENOSPC;
return (-1);
}
*olen = len;
return (0);
}

11
lib/mac/Makefile.am Normal file
View file

@ -0,0 +1,11 @@
# $Id$
AM_CPPFLAGS = -I$(top_srcdir)/include
lib_LTLIBRARIES = libcryb-mac.la
libcryb_mac_la_SOURCES = \
hmac.c
libcryb_mac_la_LIBADD = \
$(top_builddir)/lib/digest/libcryb-digest.la

110
lib/mac/hmac.c Normal file
View file

@ -0,0 +1,110 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#ifdef HAVE_SYS_ENDIAN_H
#include <sys/endian.h>
#endif
#ifdef HAVE_ENDIAN_H
#define _BSD_SOURCE
#include <endian.h>
#endif
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <cryb/sha1.h>
#include <cryb/hmac.h>
void
hmac_init(struct hmac_ctx *ctx, const uint8_t *key, size_t keylen)
{
uint8_t ipad[64];
memset(ctx, 0, sizeof *ctx);
#if 1
if (keylen > sizeof ctx->key)
sha1_complete(key, keylen, ctx->key);
else
memcpy(ctx->key, key, keylen);
#else
uint8_t keybuf[sizeof ctx->key] = { 0 };
sha1_complete(key, keylen, keybuf);
if (keylen > sizeof ctx->key)
memcpy(ctx->key, keybuf, SHA1_DIGEST_LEN);
else
memcpy(ctx->key, key, keylen);
#endif
sha1_init(&ctx->sha1_ctx);
for (unsigned int i = 0; i < sizeof ipad; ++i)
ipad[i] = 0x36 ^ ctx->key[i];
sha1_update(&ctx->sha1_ctx, ipad, sizeof ipad);
}
void
hmac_update(struct hmac_ctx *ctx, const uint8_t *buf, size_t len)
{
sha1_update(&ctx->sha1_ctx, buf, len);
}
void
hmac_final(struct hmac_ctx *ctx, uint8_t *mac)
{
uint8_t digest[20], opad[64];
sha1_final(&ctx->sha1_ctx, digest);
for (unsigned int i = 0; i < sizeof opad; ++i)
opad[i] = 0x5c ^ ctx->key[i];
sha1_init(&ctx->sha1_ctx);
sha1_update(&ctx->sha1_ctx, opad, sizeof opad);
sha1_update(&ctx->sha1_ctx, digest, sizeof digest);
sha1_final(&ctx->sha1_ctx, mac);
memset(ctx, 0, sizeof *ctx);
}
void
hmac_complete(const uint8_t *key, size_t keylen,
const uint8_t *buf, size_t len, uint8_t *mac)
{
struct hmac_ctx ctx;
hmac_init(&ctx, key, keylen);
hmac_update(&ctx, buf, len);
hmac_final(&ctx, mac);
}

20
lib/oath/Makefile.am Normal file
View file

@ -0,0 +1,20 @@
# $Id$
AM_CPPFLAGS = -I$(top_srcdir)/include
lib_LTLIBRARIES = libcryb-oath.la
libcryb_oath_la_SOURCES = \
oath_hotp.c \
oath_totp.c \
oath_key_alloc.c \
oath_key_create.c \
oath_key_dummy.c \
oath_key_from_uri.c \
oath_key_free.c \
oath_key.c
libcryb_oath_la_LIBADD = \
$(top_builddir)/lib/digest/libcryb-digest.la \
$(top_builddir)/lib/mac/libcryb-mac.la \
$(top_builddir)/lib/enc/libcryb-enc.la

134
lib/oath/oath_hotp.c Normal file
View file

@ -0,0 +1,134 @@
/*-
* Copyright (c) 2012-2013 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <stdint.h>
#include <string.h>
#include <cryb/sha1.h>
#include <cryb/hmac.h>
#include <cryb/oath.h>
#define StToNum(St) (St)
static uint32_t
DT(const uint8_t *String)
{
uint8_t OffsetBits;
int Offset;
uint32_t P;
OffsetBits = String[19] & 0x0f;
Offset = StToNum(OffsetBits);
P = (uint32_t)String[Offset + 0] << 24 |
(uint32_t)String[Offset + 1] << 16 |
(uint32_t)String[Offset + 2] << 8 |
(uint32_t)String[Offset + 3];
return (P & 0x7fffffffUL);
}
unsigned int
oath_hotp(const uint8_t *K, size_t Klen, uint64_t seq, unsigned int Digit)
{
hmac_ctx ctx;
uint8_t C[8];
uint8_t HS[20];
uint32_t Sbits, Snum;
unsigned int mod, D;
for (int i = 7; i >= 0; --i) {
C[i] = seq & 0xff;
seq >>= 8;
}
/* HS = HMAC-SHA-1(K,C) */
hmac_init(&ctx, K, Klen);
hmac_update(&ctx, (const uint8_t *)&C, sizeof C);
hmac_final(&ctx, HS);
Sbits = DT(HS);
Snum = StToNum(Sbits);
for (mod = 1; Digit > 0; --Digit)
mod *= 10;
D = Snum % mod;
return (D);
}
/*
* Computes the current code for the given key and advances the counter.
*/
unsigned int
oath_hotp_current(struct oath_key *k)
{
unsigned int code;
if (k == NULL)
return (-1);
if (k->mode != om_hotp)
return (-1);
if (k->counter == UINT64_MAX)
return (-1);
code = oath_hotp(k->key, k->keylen, k->counter, k->digits);
k->counter += 1;
return (code);
}
/*
* Compares the code provided by the user with expected values within a
* given window. Returns 1 if there was a match, 0 if not, and -1 if an
* error occurred. Also advances the counter if there was a match.
*/
int
oath_hotp_match(struct oath_key *k, unsigned int response, int window)
{
unsigned int code;
if (k == NULL)
return (-1);
if (window < 1)
return (-1);
if (k->mode != om_hotp)
return (-1);
if (k->counter >= UINT64_MAX - window)
return (-1);
for (int i = 0; i < window; ++i) {
code = oath_hotp(k->key, k->keylen, k->counter + i, k->digits);
if (code == response && !k->dummy) {
k->counter = k->counter + i;
return (1);
}
}
return (0);
}

55
lib/oath/oath_impl.h Normal file
View file

@ -0,0 +1,55 @@
/*-
* Copyright (c) 2012-2013 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#ifndef OATH_IMPL_H_INCLUDED
#define OATH_IMPL_H_INCLUDED
#if _BullseyeCoverage
#define COVERAGE_DISABLE _Pragma("BullseyeCoverage save off")
#define COVERAGE_RESTORE _Pragma("BullseyeCoverage restore")
#else
#define COVERAGE_DISABLE
#define COVERAGE_RESTORE
#endif
/*
* Use at end of switch which has no default case
*/
#define COVERAGE_NO_DEFAULT_CASE \
COVERAGE_DISABLE \
default: \
(void)0; \
COVERAGE_RESTORE
#endif

100
lib/oath/oath_key.c Normal file
View file

@ -0,0 +1,100 @@
/*-
* Copyright (c) 2013 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <sys/types.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <cryb/rfc4648.h>
#include <cryb/strlcmp.h>
#include <cryb/oath.h>
char *
oath_key_to_uri(const struct oath_key *key)
{
const char *hash;
char *tmp, *uri;
size_t kslen, urilen;
switch (key->hash) {
case oh_sha1:
hash = "SHA1";
break;
case oh_sha256:
hash = "SHA256";
break;
case oh_sha512:
hash = "SHA512";
break;
case oh_md5:
hash = "MD5";
break;
default:
return (NULL);
}
/* XXX the label should be URI-encoded */
if (key->mode == om_hotp) {
urilen = asprintf(&uri, "otpauth://%s/%s?"
"algorithm=%s&digits=%d&counter=%ju&secret=",
"hotp", key->label, hash, key->digits,
(uintmax_t)key->counter);
} else if (key->mode == om_totp) {
urilen = asprintf(&uri, "otpauth://%s/%s?"
"algorithm=%s&digits=%d&period=%u&lastused=%ju&secret=",
"totp", key->label, hash, key->digits, key->timestep,
(uintmax_t)key->lastused);
} else {
/* unreachable */
return (NULL);
}
/* compute length of base32-encoded key and append it */
kslen = base32_enclen(key->keylen) + 1;
if ((tmp = realloc(uri, urilen + kslen)) == NULL) {
free(uri);
return (NULL);
}
uri = tmp;
if (base32_encode(key->key, key->keylen, uri + urilen, &kslen) != 0) {
free(uri);
return (NULL);
}
return (uri);
}

84
lib/oath/oath_key_alloc.c Normal file
View file

@ -0,0 +1,84 @@
/*-
* Copyright (c) 2013 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <sys/mman.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <cryb/oath.h>
/*
* OATH
*
* Allocates an OATH key structure
*/
struct oath_key *
oath_key_alloc(void)
{
struct oath_key *key;
int prot, flags;
prot = PROT_READ|PROT_WRITE;
flags = MAP_ANON;
#ifdef MAP_NOCORE
flags |= MAP_NOCORE;
#endif
if ((key = mmap(NULL, sizeof *key, prot, flags, -1, 0)) != NULL) {
memset(key, 0, sizeof *key);
key->mapped = 1;
if (mlock(key, sizeof *key) == 0)
key->locked = 1;
} else {
/* openpam_log(PAM_LOG_ERROR, "mmap(): %m"); */
if ((key = calloc(sizeof *key, 1)) == NULL)
/* openpam_log(PAM_LOG_ERROR, "malloc(): %m") */;
}
return (key);
}
/**
* The =oath_key_alloc function allocates and initializes an OATH key
* structure.
*
* Keys allocated with =oath_key_alloc must be freed using =oath_key_free.
*
* >oath_key_free
*
* AUTHOR UIO
*/

177
lib/oath/oath_key_create.c Normal file
View file

@ -0,0 +1,177 @@
/*-
* Copyright (c) 2013-2014 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <stdint.h>
#include <string.h>
#include <cryb/oath.h>
#include <cryb/rand.h>
/*
* OATH
*
* Creates an OATH key with the specified parameters
*/
struct oath_key *
oath_key_create(const char *label,
enum oath_mode mode, enum oath_hash hash,
const char *keydata, size_t keylen)
{
char keybuf[OATH_MAX_KEYLEN];
struct oath_key *key;
int labellen;
/* check label */
if (label == NULL ||
(labellen = strlen(label)) > OATH_MAX_LABELLEN)
return (NULL);
/* check key length */
if (keylen > OATH_MAX_KEYLEN ||
(keydata != NULL && keylen == 0))
return (NULL);
if (keylen == 0)
keylen = 20;
/* check mode */
switch (mode) {
case om_hotp:
case om_totp:
break;
default:
return (NULL);
}
/* check hash */
switch (hash) {
case oh_undef:
hash = oh_sha1;
break;
case oh_md5:
case oh_sha1:
case oh_sha256:
case oh_sha512:
break;
default:
return (NULL);
}
/* generate key data if necessary */
if (keydata == NULL) {
if (rand_bytes((uint8_t *)keybuf, keylen) != 1)
return (NULL);
keydata = keybuf;
}
/* allocate */
if ((key = oath_key_alloc()) == NULL)
return (NULL);
/* label */
memcpy(key->label, label, labellen);
key->label[labellen] = 0;
key->labellen = labellen;
/* mode and hash */
key->mode = mode;
key->hash = hash;
/* default parameters */
key->digits = 6;
if (key->mode == om_totp)
key->timestep = 30;
/* key */
memcpy(key->key, keydata, keylen);
key->keylen = keylen;
return (key);
}
/**
* The =oath_key_create function allocates and initializes an OATH key
* structure with the specified parameters.
*
* The =label parameter must point to a string describing the key.
*
* The =mode parameter indicates the OTP algorithm to use:
*
* ;om_hotp:
* RFC 4226 HOTP
* ;om_totp:
* RFC 6238 TOTP
*
* The =hash parameter indicates which hash algorithm to use:
*
* ;oh_md5:
* RFC 1321 MD5
* ;oh_sha1:
* RFC 3174 SHA-1
* ;oh_sha256:
* RFC 6234 SHA-256
* ;oh_sha512:
* RFC 6234 SHA-512
*
* If =hash is ;oh_undef, the default algorithm (SHA-1) is used.
*
* The =keydata parameter should point to a buffer containing the raw key
* to use.
* If =keydata is NULL, a key will be randomly generated.
* Note that the strength of the generated key is dependent on the
* strength of the operating system's pseudo-random number generator.
*
* The =keylen parameter specifies the length of the provided (or
* generated) key in bytes.
* Note that some OATH HOTP / TOTP implementations do not support key
* lengths that are not a multiple of 20 bits (5 bytes).
* If =keydata is NULL and =keylen is 0, a hardcoded default of 160 bits
* (20 bytes) is used.
*
* The following key parameters are set to hardcoded default values and
* can be changed after key creation:
*
* - For HOTP keys, the initial counter value is set to 0.
* - For TOTP keys, the timestep is set to 30 seconds.
* - For both HOTP and TOTP keys, the number of digits is set to 6.
*
* Keys created with =oath_key_create must be freed using =oath_key_free.
*
* >oath_key_alloc
* >oath_key_free
*
* AUTHOR UIO
*/

78
lib/oath/oath_key_dummy.c Normal file
View file

@ -0,0 +1,78 @@
/*-
* Copyright (c) 2013 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <inttypes.h>
#include <string.h>
#include <cryb/oath.h>
/*
* OATH
*
* Creates a dummy OATH key structure
*/
struct oath_key *
oath_key_dummy(enum oath_mode mode, enum oath_hash hash, unsigned int digits)
{
struct oath_key *key;
if ((key = oath_key_alloc()) == NULL)
return (NULL);
key->dummy = 1;
key->mode = mode;
key->digits = digits;
key->counter = 0;
key->timestep = 30;
key->hash = hash;
memcpy(key->label, OATH_DUMMY_LABEL, sizeof OATH_DUMMY_LABEL);
key->labellen = sizeof OATH_DUMMY_LABEL - 1;
key->keylen = sizeof key->key;
return (key);
}
/**
* The =oath_key_dummy function allocates and initializes a dummy OATH key
* structure.
* Authentication attempts using a dummy key will always fail.
*
* Keys allocated with =oath_key_dummy must be freed using =oath_key_free.
*
* >oath_key_alloc
* >oath_key_free
*
* AUTHOR UIO
*/

77
lib/oath/oath_key_free.c Normal file
View file

@ -0,0 +1,77 @@
/*-
* Copyright (c) 2013 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <sys/mman.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <cryb/oath.h>
/*
* OATH
*
* Wipes and frees an OATH key structure
*/
void
oath_key_free(struct oath_key *key)
{
int mapped, locked;
if (key != NULL) {
mapped = key->mapped;
locked = key->locked;
memset(key, 0, sizeof *key);
if (mapped) {
if (locked)
munlock(key, sizeof *key);
munmap(key, sizeof *key);
} else {
free(key);
}
}
}
/**
* The =oath_key_free function wipes and frees an OATH key structure which
* was previously allocated using the =oath_key_alloc function.
*
* >oath_key_alloc
*
* AUTHOR UIO
*/

View file

@ -0,0 +1,93 @@
/*-
* Copyright (c) 2013 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <sys/types.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <cryb/oath.h>
#include <cryb/strlcmp.h>
/*
* OATH
*
* Loads an OATH key from a file
*/
struct oath_key *
oath_key_from_file(const char *filename)
{
struct oath_key *key;
FILE *f;
char *line;
size_t len;
if ((f = fopen(filename, "r")) == NULL)
return (NULL);
/* get first non-empty non-comment line */
line = openpam_readline(f, NULL, &len);
if (strlcmp("otpauth://", line, len) == 0) {
key = oath_key_from_uri(line);
} else {
/*
openpam_log(PAM_LOG_ERROR,
"unrecognized key file format: %s", filename);
*/
key = NULL;
}
fclose(f);
return (key);
}
/**
* The =oath_key_from_file function loads a key from the specified file.
* The file format is automatically detected.
*
* The following key file formats are supported:
*
* - otpauth URI
*
* Keys created with =oath_key_from_file must be freed using
* =oath_key_free.
*
* >oath_key_alloc
* >oath_key_free
* >oath_key_from_uri
*
* AUTHOR UIO
*/

View file

@ -0,0 +1,221 @@
/*-
* Copyright (c) 2013-2014 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <sys/types.h>
#include <inttypes.h>
#include <string.h>
#include <cryb/rfc3986.h>
#include <cryb/rfc4648.h>
#include <cryb/strlcmp.h>
#include <cryb/oath.h>
/*
* OATH
*
* Creates an OATH key from a Google otpauth URI
*/
struct oath_key *
oath_key_from_uri(const char *uri)
{
struct oath_key *key;
const char *p, *q, *r;
uintmax_t n;
char *e;
if ((key = oath_key_alloc()) == NULL)
return (NULL);
/* check method */
p = uri;
if (strlcmp("otpauth://", p, 10) != 0)
goto invalid;
p += 10;
/* check mode (hotp = event, totp = time-sync) */
if ((q = strchr(p, '/')) == NULL)
goto invalid;
if (strlcmp("hotp", p, q - p) == 0) {
key->mode = om_hotp;
} else if (strlcmp("totp", p, q - p) == 0) {
key->mode = om_totp;
} else {
goto invalid;
}
p = q + 1;
/* extract label */
if ((q = strchr(p, '?')) == NULL)
goto invalid;
key->labellen = sizeof key->label;
if (percent_decode(p, q - p, key->label, &key->labellen) != 0)
goto invalid;
p = q + 1;
/* extract parameters */
key->counter = UINT64_MAX;
key->lastused = UINT64_MAX;
while (*p != '\0') {
if ((q = strchr(p, '=')) == NULL)
goto invalid;
q = q + 1;
if ((r = strchr(p, '&')) == NULL)
r = strchr(p, '\0');
if (r < q)
/* & before = */
goto invalid;
/* p points to key, q points to value, r points to & or NUL */
if (strlcmp("secret=", p, q - p) == 0) {
if (key->keylen != 0)
/* dupe */
goto invalid;
key->keylen = sizeof key->key;
if (base32_decode(q, r - q, key->key, &key->keylen) != 0)
goto invalid;
} else if (strlcmp("algorithm=", p, q - p) == 0) {
if (key->hash != oh_undef)
/* dupe */
goto invalid;
if (strlcmp("SHA1", q, r - q) == 0)
key->hash = oh_sha1;
else if (strlcmp("SHA256", q, r - q) == 0)
key->hash = oh_sha256;
else if (strlcmp("SHA512", q, r - q) == 0)
key->hash = oh_sha512;
else if (strlcmp("MD5", q, r - q) == 0)
key->hash = oh_md5;
else
goto invalid;
} else if (strlcmp("digits=", p, q - p) == 0) {
if (key->digits != 0)
/* dupe */
goto invalid;
/* only 6 or 8 */
if (r - q != 1 || (*q != '6' && *q != '8'))
goto invalid;
key->digits = *q - '0';
} else if (strlcmp("counter=", p, q - p) == 0) {
if (key->counter != UINT64_MAX)
/* dupe */
goto invalid;
n = strtoumax(q, &e, 10);
if (e != r || n >= UINT64_MAX)
goto invalid;
key->counter = (uint64_t)n;
} else if (strlcmp("lastused=", p, q - p) == 0) {
if (key->lastused != UINT64_MAX)
/* dupe */
goto invalid;
n = strtoumax(q, &e, 10);
if (e != r || n >= UINT64_MAX)
goto invalid;
key->lastused = (uint64_t)n;
} else if (strlcmp("period=", p, q - p) == 0) {
if (key->timestep != 0)
/* dupe */
goto invalid;
n = strtoumax(q, &e, 10);
if (e != r || n > OATH_MAX_TIMESTEP)
goto invalid;
key->timestep = n;
} else if (strlcmp("issuer=", p, q - p) == 0) {
// noop for now
} else {
goto invalid;
}
/* final parameter? */
if (*r == '\0')
break;
/* skip & and continue */
p = r + 1;
}
/* sanity checks and default values */
if (key->mode == om_hotp) {
if (key->counter == UINT64_MAX)
key->counter = 0;
if (key->timestep != 0)
goto invalid;
if (key->lastused != UINT64_MAX)
goto invalid;
} else if (key->mode == om_totp) {
if (key->counter != UINT64_MAX)
goto invalid;
if (key->timestep == 0)
key->timestep = OATH_DEF_TIMESTEP;
if (key->lastused == UINT64_MAX)
key->lastused = 0;
} else {
/* unreachable */
oath_key_free(key);
return (NULL);
}
if (key->hash == oh_undef)
key->hash = oh_sha1;
if (key->digits == 0)
key->digits = 6;
if (key->keylen == 0)
goto invalid;
return (key);
invalid:
// openpam_log(PAM_LOG_NOTICE, "invalid OATH URI: %s", uri);
oath_key_free(key);
return (NULL);
}
/**
* The =oath_key_from_uri function parses a Google otpauth URI into a key
* structure.
*
* The =uri parameter points to a NUL-terminated string containing the
* URI.
*
* Keys created with =oath_key_from_uri must be freed using
* =oath_key_free.
*
* >oath_key_alloc
* >oath_key_free
* >oath_key_to_uri
*
* REFERENCES
*
* https://code.google.com/p/google-authenticator/wiki/KeyUriFormat
*
* AUTHOR UIO
*/

101
lib/oath/oath_totp.c Normal file
View file

@ -0,0 +1,101 @@
/*-
* Copyright (c) 2012-2013 Universitetet i Oslo
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <cryb/oath.h>
#define TOTP_TIME_STEP 30
unsigned int
oath_totp(const uint8_t *K, size_t Klen, unsigned int Digit)
{
time_t now;
time(&now);
return (oath_hotp(K, Klen, now / TOTP_TIME_STEP, Digit));
}
unsigned int
oath_totp_current(const struct oath_key *k)
{
unsigned int code;
uint64_t seq;
if (k == NULL)
return (-1);
if (k->mode != om_totp)
return (-1);
if (k->timestep == 0)
return (-1);
seq = time(NULL) / k->timestep;
code = oath_hotp(k->key, k->keylen, seq, k->digits);
return (code);
}
/*
* Compares the code provided by the user with expected values within a
* given window. Returns 1 if there was a match, 0 if not, and -1 if an
* error occurred.
*/
int
oath_totp_match(struct oath_key *k, unsigned int response, int window)
{
unsigned int code;
uint64_t seq;
if (k == NULL)
return (-1);
if (window < 1)
return (-1);
if (k->mode != om_totp)
return (-1);
if (k->timestep == 0)
return (-1);
seq = time(NULL) / k->timestep;
for (int i = -window; i <= window; ++i) {
if (seq + i <= k->lastused)
continue;
code = oath_hotp(k->key, k->keylen, seq + i, k->digits);
if (code == response && !k->dummy) {
k->lastused = seq;
return (1);
}
}
return (0);
}

10
lib/rand/Makefile.am Normal file
View file

@ -0,0 +1,10 @@
# $Id$
AM_CPPFLAGS = -I$(top_srcdir)/include
lib_LTLIBRARIES = libcryb-rand.la
libcryb_rand_la_SOURCES = cryb_rand.c
libcryb_rand_la_LIBADD = \
$(top_builddir)/lib/core/libcryb-core.la

64
lib/rand/cryb_rand.c Normal file
View file

@ -0,0 +1,64 @@
/*-
* Copyright (c) 2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#include "cryb/impl.h"
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <cryb/rand.h>
int
rand_bytes(uint8_t *buf, size_t len)
{
ssize_t rlen;
int fd, serrno;
if ((fd = open("/dev/random", O_RDONLY)) < 0)
return (-1);
if ((rlen = read(fd, buf, len)) < 0) {
serrno = errno;
close(fd);
errno = serrno;
return (-1);
}
close(fd);
if (rlen != (ssize_t)len) {
errno = EIO;
return (-1);
}
return (0);
}

21
lib/rsaref/Makefile.am Normal file
View file

@ -0,0 +1,21 @@
# $Id$
AM_CPPFLAGS = -include $(top_srcdir)/include/cryb/nocoverage.h
noinst_LTLIBRARIES = librsaref.la
librsaref_la_SOURCES = \
desc.c \
digit.c \
md2c.c \
md5c.c \
nn.c \
prime.c \
r_dh.c \
r_encode.c \
r_enhanc.c \
r_keygen.c \
r_random.c \
r_stdlib.c \
rsa.c
librsaref_la_CFLAGS = -DPROTOTYPES=1

56
lib/rsaref/des.h Normal file
View file

@ -0,0 +1,56 @@
/* DES.H - header file for DESC.C
*/
#ifndef _DES_H_
#define _DES_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
UINT4 subkeys[32]; /* subkeys */
UINT4 iv[2]; /* initializing vector */
UINT4 originalIV[2]; /* for restarting the context */
int encrypt; /* encrypt flag */
} DES_CBC_CTX;
typedef struct {
UINT4 subkeys[32]; /* subkeys */
UINT4 iv[2]; /* initializing vector */
UINT4 inputWhitener[2]; /* input whitener */
UINT4 outputWhitener[2]; /* output whitener */
UINT4 originalIV[2]; /* for restarting the context */
int encrypt; /* encrypt flag */
} DESX_CBC_CTX;
typedef struct {
UINT4 subkeys[3][32]; /* subkeys for three operations */
UINT4 iv[2]; /* initializing vector */
UINT4 originalIV[2]; /* for restarting the context */
int encrypt; /* encrypt flag */
} DES3_CBC_CTX;
void DES_CBCInit PROTO_LIST
((DES_CBC_CTX *, unsigned char *, unsigned char *, int));
int DES_CBCUpdate PROTO_LIST
((DES_CBC_CTX *, unsigned char *, unsigned char *, unsigned int));
void DES_CBCRestart PROTO_LIST ((DES_CBC_CTX *));
void DESX_CBCInit PROTO_LIST
((DESX_CBC_CTX *, unsigned char *, unsigned char *, int));
int DESX_CBCUpdate PROTO_LIST
((DESX_CBC_CTX *, unsigned char *, unsigned char *, unsigned int));
void DESX_CBCRestart PROTO_LIST ((DESX_CBC_CTX *));
void DES3_CBCInit PROTO_LIST
((DES3_CBC_CTX *, unsigned char *, unsigned char *, int));
int DES3_CBCUpdate PROTO_LIST
((DES3_CBC_CTX *, unsigned char *, unsigned char *, unsigned int));
void DES3_CBCRestart PROTO_LIST ((DES3_CBC_CTX *));
#ifdef __cplusplus
}
#endif
#endif

645
lib/rsaref/desc.c Normal file
View file

@ -0,0 +1,645 @@
/* DESC.C - Data Encryption Standard routines for RSAREF
Based on "Karn/Hoey/Outerbridge" implementation (KHODES)
*/
#include "global.h"
#include "rsaref.h"
#include "des.h"
static UINT2 BYTE_BIT[8] = {
0200, 0100, 040, 020, 010, 04, 02, 01
};
static UINT4 BIG_BYTE[24] = {
0x800000L, 0x400000L, 0x200000L, 0x100000L,
0x80000L, 0x40000L, 0x20000L, 0x10000L,
0x8000L, 0x4000L, 0x2000L, 0x1000L,
0x800L, 0x400L, 0x200L, 0x100L,
0x80L, 0x40L, 0x20L, 0x10L,
0x8L, 0x4L, 0x2L, 0x1L
};
static unsigned char PC1[56] = {
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
};
static unsigned char TOTAL_ROTATIONS[16] = {
1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28
};
static unsigned char PC2[48] = {
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
};
static UINT4 SP1[64] = {
0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L
};
static UINT4 SP2[64] = {
0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L
};
static UINT4 SP3[64] = {
0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L
};
static UINT4 SP4[64] = {
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L
};
static UINT4 SP5[64] = {
0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L
};
static UINT4 SP6[64] = {
0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L
};
static UINT4 SP7[64] = {
0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L
};
static UINT4 SP8[64] = {
0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L
};
static void Unpack PROTO_LIST ((unsigned char *, UINT4 *));
static void Pack PROTO_LIST ((UINT4 *, unsigned char *));
static void DESKey PROTO_LIST ((UINT4 *, unsigned char *, int));
static void CookKey PROTO_LIST ((UINT4 *, UINT4 *, int));
static void DESFunction PROTO_LIST ((UINT4 *, UINT4 *));
/* Initialize context. Caller must zeroize the context when finished.
*/
void DES_CBCInit (context, key, iv, encrypt)
DES_CBC_CTX *context; /* context */
unsigned char key[8]; /* key */
unsigned char iv[8]; /* initializing vector */
int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */
{
/* Copy encrypt flag to context.
*/
context->encrypt = encrypt;
/* Pack initializing vector into context.
*/
Pack (context->iv, iv);
/* Save the IV for use in Restart */
context->originalIV[0] = context->iv[0];
context->originalIV[1] = context->iv[1];
/* Precompute key schedule
*/
DESKey (context->subkeys, key, encrypt);
}
/* DES-CBC block update operation. Continues a DES-CBC encryption
operation, processing eight-byte message blocks, and updating
the context.
*/
int DES_CBCUpdate (context, output, input, len)
DES_CBC_CTX *context; /* context */
unsigned char *output; /* output block */
unsigned char *input; /* input block */
unsigned int len; /* length of input and output blocks */
{
UINT4 inputBlock[2], work[2];
unsigned int i;
if (len % 8)
return (RE_LEN);
for (i = 0; i < len/8; i++) {
Pack (inputBlock, &input[8*i]);
/* Chain if encrypting.
*/
if (context->encrypt) {
work[0] = inputBlock[0] ^ context->iv[0];
work[1] = inputBlock[1] ^ context->iv[1];
}
else {
work[0] = inputBlock[0];
work[1] = inputBlock[1];
}
DESFunction (work, context->subkeys);
/* Chain if decrypting, then update IV.
*/
if (context->encrypt) {
context->iv[0] = work[0];
context->iv[1] = work[1];
}
else {
work[0] ^= context->iv[0];
work[1] ^= context->iv[1];
context->iv[0] = inputBlock[0];
context->iv[1] = inputBlock[1];
}
Unpack (&output[8*i], work);
}
/* Zeroize sensitive information.
*/
R_memset ((POINTER)inputBlock, 0, sizeof (inputBlock));
R_memset ((POINTER)work, 0, sizeof (work));
return (0);
}
void DES_CBCRestart (context)
DES_CBC_CTX *context;
{
/* Reset to the original IV */
context->iv[0] = context->originalIV[0];
context->iv[1] = context->originalIV[1];
}
/* Initialize context. Caller must zeroize the context when finished.
The key has the DES key, input whitener and output whitener concatenated.
*/
void DESX_CBCInit (context, key, iv, encrypt)
DESX_CBC_CTX *context;
unsigned char key[24]; /* DES key and whiteners */
unsigned char iv[8]; /* DES initializing vector */
int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */
{
/* Copy encrypt flag to context.
*/
context->encrypt = encrypt;
/* Pack initializing vector and whiteners into context.
*/
Pack (context->iv, iv);
Pack (context->inputWhitener, key + 8);
Pack (context->outputWhitener, key + 16);
/* Save the IV for use in Restart */
context->originalIV[0] = context->iv[0];
context->originalIV[1] = context->iv[1];
/* Precompute key schedule.
*/
DESKey (context->subkeys, key, encrypt);
}
/* DESX-CBC block update operation. Continues a DESX-CBC encryption
operation, processing eight-byte message blocks, and updating
the context.
*/
int DESX_CBCUpdate (context, output, input, len)
DESX_CBC_CTX *context; /* context */
unsigned char *output; /* output block */
unsigned char *input; /* input block */
unsigned int len; /* length of input and output blocks */
{
UINT4 inputBlock[2], work[2];
unsigned int i;
if (len % 8)
return (RE_LEN);
for (i = 0; i < len/8; i++) {
Pack (inputBlock, &input[8*i]);
/* Chain if encrypting, and xor with whitener.
*/
if (context->encrypt) {
work[0] =
inputBlock[0] ^ context->iv[0] ^ context->inputWhitener[0];
work[1] =
inputBlock[1] ^ context->iv[1] ^ context->inputWhitener[1];
}
else {
work[0] = inputBlock[0] ^ context->outputWhitener[0];
work[1] = inputBlock[1] ^ context->outputWhitener[1];
}
DESFunction (work, context->subkeys);
/* Xor with whitener, chain if decrypting, then update IV.
*/
if (context->encrypt) {
work[0] ^= context->outputWhitener[0];
work[1] ^= context->outputWhitener[1];
context->iv[0] = work[0];
context->iv[1] = work[1];
}
else {
work[0] ^= context->iv[0] ^ context->inputWhitener[0];
work[1] ^= context->iv[1] ^ context->inputWhitener[1];
context->iv[0] = inputBlock[0];
context->iv[1] = inputBlock[1];
}
Unpack (&output[8*i], work);
}
/* Zeroize sensitive information.
*/
R_memset ((POINTER)inputBlock, 0, sizeof (inputBlock));
R_memset ((POINTER)work, 0, sizeof (work));
return (0);
}
void DESX_CBCRestart (context)
DESX_CBC_CTX *context;
{
/* Reset to the original IV */
context->iv[0] = context->originalIV[0];
context->iv[1] = context->originalIV[1];
}
/* Initialize context. Caller must zeroize the context when finished.
*/
void DES3_CBCInit(context, key, iv, encrypt)
DES3_CBC_CTX *context; /* context */
unsigned char key[24]; /* key */
unsigned char iv[8]; /* initializing vector */
int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */
{
/* Copy encrypt flag to context.
*/
context->encrypt = encrypt;
/* Pack initializing vector into context.
*/
Pack (context->iv, iv);
/* Save the IV for use in Restart */
context->originalIV[0] = context->iv[0];
context->originalIV[1] = context->iv[1];
/* Precompute key schedules.
*/
DESKey (context->subkeys[0], encrypt ? key : &key[16], encrypt);
DESKey (context->subkeys[1], &key[8], !encrypt);
DESKey (context->subkeys[2], encrypt ? &key[16] : key, encrypt);
}
int DES3_CBCUpdate (context, output, input, len)
DES3_CBC_CTX *context; /* context */
unsigned char *output; /* output block */
unsigned char *input; /* input block */
unsigned int len; /* length of input and output blocks */
{
UINT4 inputBlock[2], work[2];
unsigned int i;
if (len % 8)
return (RE_LEN);
for (i = 0; i < len/8; i++) {
Pack (inputBlock, &input[8*i]);
/* Chain if encrypting.
*/
if (context->encrypt) {
work[0] = inputBlock[0] ^ context->iv[0];
work[1] = inputBlock[1] ^ context->iv[1];
}
else {
work[0] = inputBlock[0];
work[1] = inputBlock[1];
}
DESFunction (work, context->subkeys[0]);
DESFunction (work, context->subkeys[1]);
DESFunction (work, context->subkeys[2]);
/* Chain if decrypting, then update IV.
*/
if (context->encrypt) {
context->iv[0] = work[0];
context->iv[1] = work[1];
}
else {
work[0] ^= context->iv[0];
work[1] ^= context->iv[1];
context->iv[0] = inputBlock[0];
context->iv[1] = inputBlock[1];
}
Unpack (&output[8*i], work);
}
/* Zeroize sensitive information.
*/
R_memset ((POINTER)inputBlock, 0, sizeof (inputBlock));
R_memset ((POINTER)work, 0, sizeof (work));
return (0);
}
void DES3_CBCRestart (context)
DES3_CBC_CTX *context;
{
/* Reset to the original IV */
context->iv[0] = context->originalIV[0];
context->iv[1] = context->originalIV[1];
}
static void Pack (into, outof)
UINT4 *into;
unsigned char *outof;
{
*into = (*outof++ & 0xffL) << 24;
*into |= (*outof++ & 0xffL) << 16;
*into |= (*outof++ & 0xffL) << 8;
*into++ |= (*outof++ & 0xffL);
*into = (*outof++ & 0xffL) << 24;
*into |= (*outof++ & 0xffL) << 16;
*into |= (*outof++ & 0xffL) << 8;
*into |= (*outof & 0xffL);
}
static void Unpack (into, outof)
unsigned char *into;
UINT4 *outof;
{
*into++ = (unsigned char)((*outof >> 24) & 0xffL);
*into++ = (unsigned char)((*outof >> 16) & 0xffL);
*into++ = (unsigned char)((*outof >> 8) & 0xffL);
*into++ = (unsigned char)( *outof++ & 0xffL);
*into++ = (unsigned char)((*outof >> 24) & 0xffL);
*into++ = (unsigned char)((*outof >> 16) & 0xffL);
*into++ = (unsigned char)((*outof >> 8) & 0xffL);
*into = (unsigned char)( *outof & 0xffL);
}
static void DESKey (subkeys, key, encrypt)
UINT4 subkeys[32];
unsigned char key[8];
int encrypt;
{
UINT4 kn[32];
int i, j, l, m, n;
unsigned char pc1m[56], pcr[56];
for (j = 0; j < 56; j++) {
l = PC1[j];
m = l & 07;
pc1m[j] = (unsigned char)((key[l >> 3] & BYTE_BIT[m]) ? 1 : 0);
}
for (i = 0; i < 16; i++) {
m = i << 1;
n = m + 1;
kn[m] = kn[n] = 0L;
for (j = 0; j < 28; j++) {
l = j + TOTAL_ROTATIONS[i];
if (l < 28)
pcr[j] = pc1m[l];
else
pcr[j] = pc1m[l - 28];
}
for (j = 28; j < 56; j++) {
l = j + TOTAL_ROTATIONS[i];
if (l < 56)
pcr[j] = pc1m[l];
else
pcr[j] = pc1m[l - 28];
}
for (j = 0; j < 24; j++) {
if (pcr[PC2[j]])
kn[m] |= BIG_BYTE[j];
if (pcr[PC2[j+24]])
kn[n] |= BIG_BYTE[j];
}
}
CookKey (subkeys, kn, encrypt);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)pc1m, 0, sizeof (pc1m));
R_memset ((POINTER)pcr, 0, sizeof (pcr));
R_memset ((POINTER)kn, 0, sizeof (kn));
}
static void CookKey (subkeys, kn, encrypt)
UINT4 *subkeys;
UINT4 *kn;
int encrypt;
{
UINT4 *cooked, *raw0, *raw1;
int increment;
unsigned int i;
raw1 = kn;
cooked = encrypt ? subkeys : &subkeys[30];
increment = encrypt ? 1 : -3;
for (i = 0; i < 16; i++, raw1++) {
raw0 = raw1++;
*cooked = (*raw0 & 0x00fc0000L) << 6;
*cooked |= (*raw0 & 0x00000fc0L) << 10;
*cooked |= (*raw1 & 0x00fc0000L) >> 10;
*cooked++ |= (*raw1 & 0x00000fc0L) >> 6;
*cooked = (*raw0 & 0x0003f000L) << 12;
*cooked |= (*raw0 & 0x0000003fL) << 16;
*cooked |= (*raw1 & 0x0003f000L) >> 4;
*cooked |= (*raw1 & 0x0000003fL);
cooked += increment;
}
}
static void DESFunction (block, subkeys)
UINT4 *block;
UINT4 *subkeys;
{
register UINT4 fval, work, right, left;
register int round;
left = block[0];
right = block[1];
work = ((left >> 4) ^ right) & 0x0f0f0f0fL;
right ^= work;
left ^= (work << 4);
work = ((left >> 16) ^ right) & 0x0000ffffL;
right ^= work;
left ^= (work << 16);
work = ((right >> 2) ^ left) & 0x33333333L;
left ^= work;
right ^= (work << 2);
work = ((right >> 8) ^ left) & 0x00ff00ffL;
left ^= work;
right ^= (work << 8);
right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
work = (left ^ right) & 0xaaaaaaaaL;
left ^= work;
right ^= work;
left = ((left << 1) | ((left >> 31) & 1L)) & 0xffffffffL;
for (round = 0; round < 8; round++) {
work = (right << 28) | (right >> 4);
work ^= *subkeys++;
fval = SP7[ work & 0x3fL];
fval |= SP5[(work >> 8) & 0x3fL];
fval |= SP3[(work >> 16) & 0x3fL];
fval |= SP1[(work >> 24) & 0x3fL];
work = right ^ *subkeys++;
fval |= SP8[ work & 0x3fL];
fval |= SP6[(work >> 8) & 0x3fL];
fval |= SP4[(work >> 16) & 0x3fL];
fval |= SP2[(work >> 24) & 0x3fL];
left ^= fval;
work = (left << 28) | (left >> 4);
work ^= *subkeys++;
fval = SP7[ work & 0x3fL];
fval |= SP5[(work >> 8) & 0x3fL];
fval |= SP3[(work >> 16) & 0x3fL];
fval |= SP1[(work >> 24) & 0x3fL];
work = left ^ *subkeys++;
fval |= SP8[ work & 0x3fL];
fval |= SP6[(work >> 8) & 0x3fL];
fval |= SP4[(work >> 16) & 0x3fL];
fval |= SP2[(work >> 24) & 0x3fL];
right ^= fval;
}
right = (right << 31) | (right >> 1);
work = (left ^ right) & 0xaaaaaaaaL;
left ^= work;
right ^= work;
left = (left << 31) | (left >> 1);
work = ((left >> 8) ^ right) & 0x00ff00ffL;
right ^= work;
left ^= (work << 8);
work = ((left >> 2) ^ right) & 0x33333333L;
right ^= work;
left ^= (work << 2);
work = ((right >> 16) ^ left) & 0x0000ffffL;
left ^= work;
right ^= (work << 16);
work = ((right >> 4) ^ left) & 0x0f0f0f0fL;
left ^= work;
right ^= (work << 4);
*block++ = right;
*block = left;
}

107
lib/rsaref/digit.c Normal file
View file

@ -0,0 +1,107 @@
/* DIGIT.C - digit arithmetic routines
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
#include "global.h"
#include "rsaref.h"
#include "nn.h"
#include "digit.h"
/* Computes a = b * c, where b and c are digits.
Lengths: a[2].
*/
void NN_DigitMult (a, b, c)
NN_DIGIT a[2], b, c;
{
NN_DIGIT t, u;
NN_HALF_DIGIT bHigh, bLow, cHigh, cLow;
bHigh = (NN_HALF_DIGIT)HIGH_HALF (b);
bLow = (NN_HALF_DIGIT)LOW_HALF (b);
cHigh = (NN_HALF_DIGIT)HIGH_HALF (c);
cLow = (NN_HALF_DIGIT)LOW_HALF (c);
a[0] = (NN_DIGIT)bLow * (NN_DIGIT)cLow;
t = (NN_DIGIT)bLow * (NN_DIGIT)cHigh;
u = (NN_DIGIT)bHigh * (NN_DIGIT)cLow;
a[1] = (NN_DIGIT)bHigh * (NN_DIGIT)cHigh;
if ((t += u) < u)
a[1] += TO_HIGH_HALF (1);
u = TO_HIGH_HALF (t);
if ((a[0] += u) < u)
a[1]++;
a[1] += HIGH_HALF (t);
}
/* Sets a = b / c, where a and c are digits.
Lengths: b[2].
Assumes b[1] < c and HIGH_HALF (c) > 0. For efficiency, c should be
normalized.
*/
void NN_DigitDiv (a, b, c)
NN_DIGIT *a, b[2], c;
{
NN_DIGIT t[2], u, v;
NN_HALF_DIGIT aHigh, aLow, cHigh, cLow;
cHigh = (NN_HALF_DIGIT)HIGH_HALF (c);
cLow = (NN_HALF_DIGIT)LOW_HALF (c);
t[0] = b[0];
t[1] = b[1];
/* Underestimate high half of quotient and subtract.
*/
if (cHigh == MAX_NN_HALF_DIGIT)
aHigh = (NN_HALF_DIGIT)HIGH_HALF (t[1]);
else
aHigh = (NN_HALF_DIGIT)(t[1] / (cHigh + 1));
u = (NN_DIGIT)aHigh * (NN_DIGIT)cLow;
v = (NN_DIGIT)aHigh * (NN_DIGIT)cHigh;
if ((t[0] -= TO_HIGH_HALF (u)) > (MAX_NN_DIGIT - TO_HIGH_HALF (u)))
t[1]--;
t[1] -= HIGH_HALF (u);
t[1] -= v;
/* Correct estimate.
*/
while ((t[1] > cHigh) ||
((t[1] == cHigh) && (t[0] >= TO_HIGH_HALF (cLow)))) {
if ((t[0] -= TO_HIGH_HALF (cLow)) > MAX_NN_DIGIT - TO_HIGH_HALF (cLow))
t[1]--;
t[1] -= cHigh;
aHigh++;
}
/* Underestimate low half of quotient and subtract.
*/
if (cHigh == MAX_NN_HALF_DIGIT)
aLow = (NN_HALF_DIGIT)LOW_HALF (t[1]);
else
aLow =
(NN_HALF_DIGIT)((TO_HIGH_HALF (t[1]) + HIGH_HALF (t[0])) / (cHigh + 1));
u = (NN_DIGIT)aLow * (NN_DIGIT)cLow;
v = (NN_DIGIT)aLow * (NN_DIGIT)cHigh;
if ((t[0] -= u) > (MAX_NN_DIGIT - u))
t[1]--;
if ((t[0] -= TO_HIGH_HALF (v)) > (MAX_NN_DIGIT - TO_HIGH_HALF (v)))
t[1]--;
t[1] -= HIGH_HALF (v);
/* Correct estimate.
*/
while ((t[1] > 0) || ((t[1] == 0) && t[0] >= c)) {
if ((t[0] -= c) > (MAX_NN_DIGIT - c))
t[1]--;
aLow++;
}
*a = TO_HIGH_HALF (aHigh) + aLow;
}

9
lib/rsaref/digit.h Normal file
View file

@ -0,0 +1,9 @@
/* DIGIT.H - header file for DIGIT.C
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
void NN_DigitMult PROTO_LIST ((NN_DIGIT [2], NN_DIGIT, NN_DIGIT));
void NN_DigitDiv PROTO_LIST ((NN_DIGIT *, NN_DIGIT [2], NN_DIGIT));

47
lib/rsaref/global.h Normal file
View file

@ -0,0 +1,47 @@
/* GLOBAL.H - RSAREF types and constants
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
#ifndef _GLOBAL_H_
#define _GLOBAL_H_ 1
/* PROTOTYPES should be set to one if and only if the compiler supports
function argument prototyping.
The following makes PROTOTYPES default to 1 if it has not already been
defined as 0 with C compiler flags.
*/
#ifndef PROTOTYPES
#define PROTOTYPES 1
#endif
/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;
/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;
/* UINT4 defines a four byte word */
typedef unsigned int UINT4;
#ifndef NULL_PTR
#define NULL_PTR ((POINTER)0)
#endif
#ifndef UNUSED_ARG
#define UNUSED_ARG(x) x = *(&x);
#endif
/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
returns an empty list.
*/
#if PROTOTYPES
#define PROTO_LIST(list) list
#else
#define PROTO_LIST(list) ()
#endif
#endif /* end _GLOBAL_H_ */

45
lib/rsaref/md2.h Normal file
View file

@ -0,0 +1,45 @@
/* MD2.H - header file for MD2C.C
*/
/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
rights reserved.
License to copy and use this software is granted for
non-commercial Internet Privacy-Enhanced Mail provided that it is
identified as the "RSA Data Security, Inc. MD2 Message Digest
Algorithm" in all material mentioning or referencing this software
or this function.
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 _MD2_H_
#define _MD2_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
unsigned char state[16]; /* state */
unsigned char checksum[16]; /* checksum */
unsigned int count; /* number of bytes, modulo 16 */
unsigned char buffer[16]; /* input buffer */
} MD2_CTX;
void MD2Init PROTO_LIST ((MD2_CTX *));
void MD2Update PROTO_LIST
((MD2_CTX *, unsigned char *, unsigned int));
void MD2Final PROTO_LIST ((unsigned char [16], MD2_CTX *));
#ifdef __cplusplus
}
#endif
#endif

218
lib/rsaref/md2c.c Normal file
View file

@ -0,0 +1,218 @@
/* MD2C.C - RSA Data Security, Inc., MD2 message-digest algorithm
*/
/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
rights reserved.
License to copy and use this software is granted for
non-commercial Internet Privacy-Enhanced Mail provided that it is
identified as the "RSA Data Security, Inc. MD2 Message Digest
Algorithm" in all material mentioning or referencing this software
or this function.
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.
*/
#include "global.h"
#include "md2.h"
static void MD2Transform PROTO_LIST
((unsigned char [16], unsigned char [16], unsigned char [16]));
static void MD2_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
static void MD2_memset PROTO_LIST ((POINTER, int, unsigned int));
/* Permutation of 0..255 constructed from the digits of pi. It gives a
"random" nonlinear byte substitution operation.
*/
static unsigned char PI_SUBST[256] = {
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
31, 26, 219, 153, 141, 51, 159, 17, 131, 20
};
static unsigned char *PADDING[] = {
(unsigned char *)"",
(unsigned char *)"\001",
(unsigned char *)"\002\002",
(unsigned char *)"\003\003\003",
(unsigned char *)"\004\004\004\004",
(unsigned char *)"\005\005\005\005\005",
(unsigned char *)"\006\006\006\006\006\006",
(unsigned char *)"\007\007\007\007\007\007\007",
(unsigned char *)"\010\010\010\010\010\010\010\010",
(unsigned char *)"\011\011\011\011\011\011\011\011\011",
(unsigned char *)"\012\012\012\012\012\012\012\012\012\012",
(unsigned char *)"\013\013\013\013\013\013\013\013\013\013\013",
(unsigned char *)"\014\014\014\014\014\014\014\014\014\014\014\014",
(unsigned char *)
"\015\015\015\015\015\015\015\015\015\015\015\015\015",
(unsigned char *)
"\016\016\016\016\016\016\016\016\016\016\016\016\016\016",
(unsigned char *)
"\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017",
(unsigned char *)
"\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020"
};
/* MD2 initialization. Begins an MD2 operation, writing a new context.
*/
void MD2Init (context)
MD2_CTX *context; /* context */
{
context->count = 0;
MD2_memset ((POINTER)context->state, 0, sizeof (context->state));
MD2_memset
((POINTER)context->checksum, 0, sizeof (context->checksum));
}
/* MD2 block update operation. Continues an MD2 message-digest
operation, processing another message block, and updating the
context.
*/
void MD2Update (context, input, inputLen)
MD2_CTX *context; /* context */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
{
unsigned int i, index, partLen;
/* Update number of bytes mod 16 */
index = context->count;
context->count = (index + inputLen) & 0xf;
partLen = 16 - index;
/* Transform as many times as possible.
*/
if (inputLen >= partLen) {
MD2_memcpy
((POINTER)&context->buffer[index], (POINTER)input, partLen);
MD2Transform (context->state, context->checksum, context->buffer);
for (i = partLen; i + 15 < inputLen; i += 16)
MD2Transform (context->state, context->checksum, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
MD2_memcpy
((POINTER)&context->buffer[index], (POINTER)&input[i],
inputLen-i);
}
/* MD2 finalization. Ends an MD2 message-digest operation, writing the
message digest and zeroizing the context.
*/
void MD2Final (digest, context)
unsigned char digest[16]; /* message digest */
MD2_CTX *context; /* context */
{
unsigned int index, padLen;
/* Pad out to multiple of 16.
*/
index = context->count;
padLen = 16 - index;
MD2Update (context, PADDING[padLen], padLen);
/* Extend with checksum */
MD2Update (context, context->checksum, 16);
/* Store state in digest */
MD2_memcpy ((POINTER)digest, (POINTER)context->state, 16);
/* Zeroize sensitive information.
*/
MD2_memset ((POINTER)context, 0, sizeof (*context));
}
/* MD2 basic transformation. Transforms state and updates checksum
based on block.
*/
static void MD2Transform (state, checksum, block)
unsigned char state[16];
unsigned char checksum[16];
unsigned char block[16];
{
unsigned int i, j, t;
unsigned char x[48];
/* Form encryption block from state, block, state ^ block.
*/
MD2_memcpy ((POINTER)x, (POINTER)state, 16);
MD2_memcpy ((POINTER)x+16, (POINTER)block, 16);
for (i = 0; i < 16; i++)
x[i+32] = state[i] ^ block[i];
/* Encrypt block (18 rounds).
*/
t = 0;
for (i = 0; i < 18; i++) {
for (j = 0; j < 48; j++)
t = x[j] ^= PI_SUBST[t];
t = (t + i) & 0xff;
}
/* Save new state */
MD2_memcpy ((POINTER)state, (POINTER)x, 16);
/* Update checksum.
*/
t = checksum[15];
for (i = 0; i < 16; i++)
t = checksum[i] ^= PI_SUBST[block[i] ^ t];
/* Zeroize sensitive information.
*/
MD2_memset ((POINTER)x, 0, sizeof (x));
}
/* Note: Replace "for loop" with standard memcpy if possible.
*/
static void MD2_memcpy (output, input, len)
POINTER output;
POINTER input;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
output[i] = input[i];
}
/* Note: Replace "for loop" with standard memset if possible.
*/
static void MD2_memset (output, value, len)
POINTER output;
int value;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
((char *)output)[i] = (char)value;
}

49
lib/rsaref/md5.h Normal file
View file

@ -0,0 +1,49 @@
/* MD5.H - header file for MD5C.C
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. 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 _MD5_H_
#define _MD5_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/* MD5 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;
void MD5Init PROTO_LIST ((MD5_CTX *));
void MD5Update PROTO_LIST
((MD5_CTX *, unsigned char *, unsigned int));
void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
#ifdef __cplusplus
}
#endif
#endif

334
lib/rsaref/md5c.c Normal file
View file

@ -0,0 +1,334 @@
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. 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.
*/
#include "global.h"
#include "md5.h"
/* Constants for MD5Transform routine.
*/
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
static void Encode PROTO_LIST
((unsigned char *, UINT4 *, unsigned int));
static void Decode PROTO_LIST
((UINT4 *, unsigned char *, unsigned int));
static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
void MD5Init (context)
MD5_CTX *context; /* context */
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.
*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
void MD5Update (context, input, inputLen)
MD5_CTX *context; /* context */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.
*/
if (inputLen >= partLen) {
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)input, partLen);
MD5Transform (context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)&input[i],
inputLen-i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
void MD5Final (digest, context)
unsigned char digest[16]; /* message digest */
MD5_CTX *context; /* context */
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64.
*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update (context, PADDING, padLen);
/* Append length (before padding) */
MD5Update (context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
/* Zeroize sensitive information.
*/
MD5_memset ((POINTER)context, 0, sizeof (*context));
}
/* MD5 basic transformation. Transforms state based on block.
*/
static void MD5Transform (state, block)
UINT4 state[4];
unsigned char block[64];
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information.
*/
MD5_memset ((POINTER)x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
a multiple of 4.
*/
static void Encode (output, input, len)
unsigned char *output;
UINT4 *input;
unsigned int len;
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
a multiple of 4.
*/
static void Decode (output, input, len)
UINT4 *output;
unsigned char *input;
unsigned int len;
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
/* Note: Replace "for loop" with standard memcpy if possible.
*/
static void MD5_memcpy (output, input, len)
POINTER output;
POINTER input;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
output[i] = input[i];
}
/* Note: Replace "for loop" with standard memset if possible.
*/
static void MD5_memset (output, value, len)
POINTER output;
int value;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
((char *)output)[i] = (char)value;
}

622
lib/rsaref/nn.c Normal file
View file

@ -0,0 +1,622 @@
/* NN.C - natural numbers routines
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
#include "global.h"
#include "rsaref.h"
#include "nn.h"
#include "digit.h"
static NN_DIGIT NN_AddDigitMult PROTO_LIST
((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int));
static NN_DIGIT NN_SubDigitMult PROTO_LIST
((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int));
static unsigned int NN_DigitBits PROTO_LIST ((NN_DIGIT));
/* Decodes character string b into a, where character string is ordered
from most to least significant.
Lengths: a[digits], b[len].
Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most
significant bytes are truncated.)
*/
void NN_Decode (a, digits, b, len)
NN_DIGIT *a;
unsigned char *b;
unsigned int digits, len;
{
NN_DIGIT t;
int j;
unsigned int i, u;
for (i = 0, j = len - 1; i < digits && j >= 0; i++) {
t = 0;
for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
t |= ((NN_DIGIT)b[j]) << u;
a[i] = t;
}
for (; i < digits; i++)
a[i] = 0;
}
/* Encodes b into character string a, where character string is ordered
from most to least significant.
Lengths: a[len], b[digits].
Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant
digits are truncated.)
*/
void NN_Encode (a, len, b, digits)
NN_DIGIT *b;
unsigned char *a;
unsigned int digits, len;
{
NN_DIGIT t;
int j;
unsigned int i, u;
for (i = 0, j = len - 1; i < digits && j >= 0; i++) {
t = b[i];
for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
a[j] = (unsigned char)(t >> u);
}
for (; j >= 0; j--)
a[j] = 0;
}
/* Assigns a = b.
Lengths: a[digits], b[digits].
*/
void NN_Assign (a, b, digits)
NN_DIGIT *a, *b;
unsigned int digits;
{
unsigned int i;
for (i = 0; i < digits; i++)
a[i] = b[i];
}
/* Assigns a = 0.
Lengths: a[digits].
*/
void NN_AssignZero (a, digits)
NN_DIGIT *a;
unsigned int digits;
{
unsigned int i;
for (i = 0; i < digits; i++)
a[i] = 0;
}
/* Assigns a = 2^b.
Lengths: a[digits].
Requires b < digits * NN_DIGIT_BITS.
*/
void NN_Assign2Exp (a, b, digits)
NN_DIGIT *a;
unsigned int b, digits;
{
NN_AssignZero (a, digits);
if (b >= digits * NN_DIGIT_BITS)
return;
a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS);
}
/* Computes a = b + c. Returns carry.
Lengths: a[digits], b[digits], c[digits].
*/
NN_DIGIT NN_Add (a, b, c, digits)
NN_DIGIT *a, *b, *c;
unsigned int digits;
{
NN_DIGIT ai, carry;
unsigned int i;
carry = 0;
for (i = 0; i < digits; i++) {
if ((ai = b[i] + carry) < carry)
ai = c[i];
else if ((ai += c[i]) < c[i])
carry = 1;
else
carry = 0;
a[i] = ai;
}
return (carry);
}
/* Computes a = b - c. Returns borrow.
Lengths: a[digits], b[digits], c[digits].
*/
NN_DIGIT NN_Sub (a, b, c, digits)
NN_DIGIT *a, *b, *c;
unsigned int digits;
{
NN_DIGIT ai, borrow;
unsigned int i;
borrow = 0;
for (i = 0; i < digits; i++) {
if ((ai = b[i] - borrow) > (MAX_NN_DIGIT - borrow))
ai = MAX_NN_DIGIT - c[i];
else if ((ai -= c[i]) > (MAX_NN_DIGIT - c[i]))
borrow = 1;
else
borrow = 0;
a[i] = ai;
}
return (borrow);
}
/* Computes a = b * c.
Lengths: a[2*digits], b[digits], c[digits].
Assumes digits < MAX_NN_DIGITS.
*/
void NN_Mult (a, b, c, digits)
NN_DIGIT *a, *b, *c;
unsigned int digits;
{
NN_DIGIT t[2*MAX_NN_DIGITS];
unsigned int bDigits, cDigits, i;
NN_AssignZero (t, 2 * digits);
bDigits = NN_Digits (b, digits);
cDigits = NN_Digits (c, digits);
for (i = 0; i < bDigits; i++)
t[i+cDigits] += NN_AddDigitMult (&t[i], &t[i], b[i], c, cDigits);
NN_Assign (a, t, 2 * digits);
/* Zeroize potentially sensitive information.
*/
R_memset ((POINTER)t, 0, sizeof (t));
}
/* Computes a = b * 2^c (i.e., shifts left c bits), returning carry.
Lengths: a[digits], b[digits].
Requires c < NN_DIGIT_BITS.
*/
NN_DIGIT NN_LShift (a, b, c, digits)
NN_DIGIT *a, *b;
unsigned int c, digits;
{
NN_DIGIT bi, carry;
unsigned int i, t;
if (c >= NN_DIGIT_BITS)
return (0);
t = NN_DIGIT_BITS - c;
carry = 0;
for (i = 0; i < digits; i++) {
bi = b[i];
a[i] = (bi << c) | carry;
carry = c ? (bi >> t) : 0;
}
return (carry);
}
/* Computes a = c div 2^c (i.e., shifts right c bits), returning carry.
Lengths: a[digits], b[digits].
Requires: c < NN_DIGIT_BITS.
*/
NN_DIGIT NN_RShift (a, b, c, digits)
NN_DIGIT *a, *b;
unsigned int c, digits;
{
NN_DIGIT bi, carry;
int i;
unsigned int t;
if (c >= NN_DIGIT_BITS)
return (0);
t = NN_DIGIT_BITS - c;
carry = 0;
for (i = digits - 1; i >= 0; i--) {
bi = b[i];
a[i] = (bi >> c) | carry;
carry = c ? (bi << t) : 0;
}
return (carry);
}
/* Computes a = c div d and b = c mod d.
Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits].
Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS,
dDigits < MAX_NN_DIGITS.
*/
void NN_Div (a, b, c, cDigits, d, dDigits)
NN_DIGIT *a, *b, *c, *d;
unsigned int cDigits, dDigits;
{
NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], t;
int i;
unsigned int ddDigits, shift;
ddDigits = NN_Digits (d, dDigits);
if (ddDigits == 0)
return;
/* Normalize operands.
*/
shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]);
NN_AssignZero (cc, ddDigits);
cc[cDigits] = NN_LShift (cc, c, shift, cDigits);
NN_LShift (dd, d, shift, ddDigits);
t = dd[ddDigits-1];
NN_AssignZero (a, cDigits);
for (i = cDigits-ddDigits; i >= 0; i--) {
/* Underestimate quotient digit and subtract.
*/
if (t == MAX_NN_DIGIT)
ai = cc[i+ddDigits];
else
NN_DigitDiv (&ai, &cc[i+ddDigits-1], t + 1);
cc[i+ddDigits] -= NN_SubDigitMult (&cc[i], &cc[i], ai, dd, ddDigits);
/* Correct estimate.
*/
while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0)) {
ai++;
cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits);
}
a[i] = ai;
}
/* Restore result.
*/
NN_AssignZero (b, dDigits);
NN_RShift (b, cc, shift, ddDigits);
/* Zeroize potentially sensitive information.
*/
R_memset ((POINTER)cc, 0, sizeof (cc));
R_memset ((POINTER)dd, 0, sizeof (dd));
}
/* Computes a = b mod c.
Lengths: a[cDigits], b[bDigits], c[cDigits].
Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS.
*/
void NN_Mod (a, b, bDigits, c, cDigits)
NN_DIGIT *a, *b, *c;
unsigned int bDigits, cDigits;
{
NN_DIGIT t[2 * MAX_NN_DIGITS];
NN_Div (t, a, b, bDigits, c, cDigits);
/* Zeroize potentially sensitive information.
*/
R_memset ((POINTER)t, 0, sizeof (t));
}
/* Computes a = b * c mod d.
Lengths: a[digits], b[digits], c[digits], d[digits].
Assumes d > 0, digits < MAX_NN_DIGITS.
*/
void NN_ModMult (a, b, c, d, digits)
NN_DIGIT *a, *b, *c, *d;
unsigned int digits;
{
NN_DIGIT t[2*MAX_NN_DIGITS];
NN_Mult (t, b, c, digits);
NN_Mod (a, t, 2 * digits, d, digits);
/* Zeroize potentially sensitive information.
*/
R_memset ((POINTER)t, 0, sizeof (t));
}
/* Computes a = b^c mod d.
Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits].
Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS.
*/
void NN_ModExp (a, b, c, cDigits, d, dDigits)
NN_DIGIT *a, *b, *c, *d;
unsigned int cDigits, dDigits;
{
NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS];
int i;
unsigned int ciBits, j, s;
/* Store b, b^2 mod d, and b^3 mod d.
*/
NN_Assign (bPower[0], b, dDigits);
NN_ModMult (bPower[1], bPower[0], b, d, dDigits);
NN_ModMult (bPower[2], bPower[1], b, d, dDigits);
NN_ASSIGN_DIGIT (t, 1, dDigits);
cDigits = NN_Digits (c, cDigits);
for (i = cDigits - 1; i >= 0; i--) {
ci = c[i];
ciBits = NN_DIGIT_BITS;
/* Scan past leading zero bits of most significant digit.
*/
if (i == (int)(cDigits - 1)) {
while (! DIGIT_2MSB (ci)) {
ci <<= 2;
ciBits -= 2;
}
}
for (j = 0; j < ciBits; j += 2, ci <<= 2) {
/* Compute t = t^4 * b^s mod d, where s = two MSB's of ci.
*/
NN_ModMult (t, t, t, d, dDigits);
NN_ModMult (t, t, t, d, dDigits);
if ((s = DIGIT_2MSB (ci)) != 0)
NN_ModMult (t, t, bPower[s-1], d, dDigits);
}
}
NN_Assign (a, t, dDigits);
/* Zeroize potentially sensitive information.
*/
R_memset ((POINTER)bPower, 0, sizeof (bPower));
R_memset ((POINTER)t, 0, sizeof (t));
}
/* Compute a = 1/b mod c, assuming inverse exists.
Lengths: a[digits], b[digits], c[digits].
Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS.
*/
void NN_ModInv (a, b, c, digits)
NN_DIGIT *a, *b, *c;
unsigned int digits;
{
NN_DIGIT q[MAX_NN_DIGITS], t1[MAX_NN_DIGITS], t3[MAX_NN_DIGITS],
u1[MAX_NN_DIGITS], u3[MAX_NN_DIGITS], v1[MAX_NN_DIGITS],
v3[MAX_NN_DIGITS], w[2*MAX_NN_DIGITS];
int u1Sign;
/* Apply extended Euclidean algorithm, modified to avoid negative
numbers.
*/
NN_ASSIGN_DIGIT (u1, 1, digits);
NN_AssignZero (v1, digits);
NN_Assign (u3, b, digits);
NN_Assign (v3, c, digits);
u1Sign = 1;
while (! NN_Zero (v3, digits)) {
NN_Div (q, t3, u3, digits, v3, digits);
NN_Mult (w, q, v1, digits);
NN_Add (t1, u1, w, digits);
NN_Assign (u1, v1, digits);
NN_Assign (v1, t1, digits);
NN_Assign (u3, v3, digits);
NN_Assign (v3, t3, digits);
u1Sign = -u1Sign;
}
/* Negate result if sign is negative.
*/
if (u1Sign < 0)
NN_Sub (a, c, u1, digits);
else
NN_Assign (a, u1, digits);
/* Zeroize potentially sensitive information.
*/
R_memset ((POINTER)q, 0, sizeof (q));
R_memset ((POINTER)t1, 0, sizeof (t1));
R_memset ((POINTER)t3, 0, sizeof (t3));
R_memset ((POINTER)u1, 0, sizeof (u1));
R_memset ((POINTER)u3, 0, sizeof (u3));
R_memset ((POINTER)v1, 0, sizeof (v1));
R_memset ((POINTER)v3, 0, sizeof (v3));
R_memset ((POINTER)w, 0, sizeof (w));
}
/* Computes a = gcd(b, c).
Lengths: a[digits], b[digits], c[digits].
Assumes b > c, digits < MAX_NN_DIGITS.
*/
void NN_Gcd (a, b, c, digits)
NN_DIGIT *a, *b, *c;
unsigned int digits;
{
NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS];
NN_Assign (u, b, digits);
NN_Assign (v, c, digits);
while (! NN_Zero (v, digits)) {
NN_Mod (t, u, digits, v, digits);
NN_Assign (u, v, digits);
NN_Assign (v, t, digits);
}
NN_Assign (a, u, digits);
/* Zeroize potentially sensitive information.
*/
R_memset ((POINTER)t, 0, sizeof (t));
R_memset ((POINTER)u, 0, sizeof (u));
R_memset ((POINTER)v, 0, sizeof (v));
}
/* Returns sign of a - b.
Lengths: a[digits], b[digits].
*/
int NN_Cmp (a, b, digits)
NN_DIGIT *a, *b;
unsigned int digits;
{
int i;
for (i = digits - 1; i >= 0; i--) {
if (a[i] > b[i])
return (1);
if (a[i] < b[i])
return (-1);
}
return (0);
}
/* Returns nonzero iff a is zero.
Lengths: a[digits].
*/
int NN_Zero (a, digits)
NN_DIGIT *a;
unsigned int digits;
{
unsigned int i;
for (i = 0; i < digits; i++)
if (a[i])
return (0);
return (1);
}
/* Returns the significant length of a in bits.
Lengths: a[digits].
*/
unsigned int NN_Bits (a, digits)
NN_DIGIT *a;
unsigned int digits;
{
if ((digits = NN_Digits (a, digits)) == 0)
return (0);
return ((digits - 1) * NN_DIGIT_BITS + NN_DigitBits (a[digits-1]));
}
/* Returns the significant length of a in digits.
Lengths: a[digits].
*/
unsigned int NN_Digits (a, digits)
NN_DIGIT *a;
unsigned int digits;
{
int i;
for (i = digits - 1; i >= 0; i--)
if (a[i])
break;
return (i + 1);
}
/* Computes a = b + c*d, where c is a digit. Returns carry.
Lengths: a[digits], b[digits], d[digits].
*/
static NN_DIGIT NN_AddDigitMult (a, b, c, d, digits)
NN_DIGIT *a, *b, c, *d;
unsigned int digits;
{
NN_DIGIT carry, t[2];
unsigned int i;
if (c == 0)
return (0);
carry = 0;
for (i = 0; i < digits; i++) {
NN_DigitMult (t, c, d[i]);
if ((a[i] = b[i] + carry) < carry)
carry = 1;
else
carry = 0;
if ((a[i] += t[0]) < t[0])
carry++;
carry += t[1];
}
return (carry);
}
/* Computes a = b - c*d, where c is a digit. Returns borrow.
Lengths: a[digits], b[digits], d[digits].
*/
static NN_DIGIT NN_SubDigitMult (a, b, c, d, digits)
NN_DIGIT *a, *b, c, *d;
unsigned int digits;
{
NN_DIGIT borrow, t[2];
unsigned int i;
if (c == 0)
return (0);
borrow = 0;
for (i = 0; i < digits; i++) {
NN_DigitMult (t, c, d[i]);
if ((a[i] = b[i] - borrow) > (MAX_NN_DIGIT - borrow))
borrow = 1;
else
borrow = 0;
if ((a[i] -= t[0]) > (MAX_NN_DIGIT - t[0]))
borrow++;
borrow += t[1];
}
return (borrow);
}
/* Returns the significant length of a in bits, where a is a digit.
*/
static unsigned int NN_DigitBits (a)
NN_DIGIT a;
{
unsigned int i;
for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1)
if (a == 0)
break;
return (i);
}

114
lib/rsaref/nn.h Normal file
View file

@ -0,0 +1,114 @@
/* NN.H - header file for NN.C
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
/* Type definitions.
*/
typedef UINT4 NN_DIGIT;
typedef UINT2 NN_HALF_DIGIT;
/* Constants.
Note: MAX_NN_DIGITS is long enough to hold any RSA modulus, plus
one more digit as required by R_GeneratePEMKeys (for n and phiN,
whose lengths must be even). All natural numbers have at most
MAX_NN_DIGITS digits, except for double-length intermediate values
in NN_Mult (t), NN_ModMult (t), NN_ModInv (w), and NN_Div (c).
*/
/* Length of digit in bits */
#define NN_DIGIT_BITS 32
#define NN_HALF_DIGIT_BITS 16
/* Length of digit in bytes */
#define NN_DIGIT_LEN (NN_DIGIT_BITS / 8)
/* Maximum length in digits */
#define MAX_NN_DIGITS \
((MAX_RSA_MODULUS_LEN + NN_DIGIT_LEN - 1) / NN_DIGIT_LEN + 1)
/* Maximum digits */
#define MAX_NN_DIGIT 0xffffffff
#define MAX_NN_HALF_DIGIT 0xffff
/* Macros.
*/
#define LOW_HALF(x) ((x) & MAX_NN_HALF_DIGIT)
#define HIGH_HALF(x) (((x) >> NN_HALF_DIGIT_BITS) & MAX_NN_HALF_DIGIT)
#define TO_HIGH_HALF(x) (((NN_DIGIT)(x)) << NN_HALF_DIGIT_BITS)
#define DIGIT_MSB(x) (unsigned int)(((x) >> (NN_DIGIT_BITS - 1)) & 1)
#define DIGIT_2MSB(x) (unsigned int)(((x) >> (NN_DIGIT_BITS - 2)) & 3)
/* CONVERSIONS
NN_Decode (a, digits, b, len) Decodes character string b into a.
NN_Encode (a, len, b, digits) Encodes a into character string b.
ASSIGNMENTS
NN_Assign (a, b, digits) Assigns a = b.
NN_ASSIGN_DIGIT (a, b, digits) Assigns a = b, where b is a digit.
NN_AssignZero (a, b, digits) Assigns a = 0.
NN_Assign2Exp (a, b, digits) Assigns a = 2^b.
ARITHMETIC OPERATIONS
NN_Add (a, b, c, digits) Computes a = b + c.
NN_Sub (a, b, c, digits) Computes a = b - c.
NN_Mult (a, b, c, digits) Computes a = b * c.
NN_LShift (a, b, c, digits) Computes a = b * 2^c.
NN_RShift (a, b, c, digits) Computes a = b / 2^c.
NN_Div (a, b, c, cDigits, d, dDigits) Computes a = c div d and b = c mod d.
NUMBER THEORY
NN_Mod (a, b, bDigits, c, cDigits) Computes a = b mod c.
NN_ModMult (a, b, c, d, digits) Computes a = b * c mod d.
NN_ModExp (a, b, c, cDigits, d, dDigits) Computes a = b^c mod d.
NN_ModInv (a, b, c, digits) Computes a = 1/b mod c.
NN_Gcd (a, b, c, digits) Computes a = gcd (b, c).
OTHER OPERATIONS
NN_EVEN (a, digits) Returns 1 iff a is even.
NN_Cmp (a, b, digits) Returns sign of a - b.
NN_EQUAL (a, digits) Returns 1 iff a = b.
NN_Zero (a, digits) Returns 1 iff a = 0.
NN_Digits (a, digits) Returns significant length of a in digits.
NN_Bits (a, digits) Returns significant length of a in bits.
*/
void NN_Decode PROTO_LIST
((NN_DIGIT *, unsigned int, unsigned char *, unsigned int));
void NN_Encode PROTO_LIST
((unsigned char *, unsigned int, NN_DIGIT *, unsigned int));
void NN_Assign PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, unsigned int));
void NN_AssignZero PROTO_LIST ((NN_DIGIT *, unsigned int));
void NN_Assign2Exp PROTO_LIST ((NN_DIGIT *, unsigned int, unsigned int));
NN_DIGIT NN_Add PROTO_LIST
((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int));
NN_DIGIT NN_Sub PROTO_LIST
((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int));
void NN_Mult PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int));
void NN_Div PROTO_LIST
((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *,
unsigned int));
NN_DIGIT NN_LShift PROTO_LIST
((NN_DIGIT *, NN_DIGIT *, unsigned int, unsigned int));
NN_DIGIT NN_RShift PROTO_LIST
((NN_DIGIT *, NN_DIGIT *, unsigned int, unsigned int));
void NN_Mod PROTO_LIST
((NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int));
void NN_ModMult PROTO_LIST
((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int));
void NN_ModExp PROTO_LIST
((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *,
unsigned int));
void NN_ModInv PROTO_LIST
((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int));
void NN_Gcd PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int));
int NN_Cmp PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, unsigned int));
int NN_Zero PROTO_LIST ((NN_DIGIT *, unsigned int));
unsigned int NN_Bits PROTO_LIST ((NN_DIGIT *, unsigned int));
unsigned int NN_Digits PROTO_LIST ((NN_DIGIT *, unsigned int));
#define NN_ASSIGN_DIGIT(a, b, digits) {NN_AssignZero (a, digits); a[0] = b;}
#define NN_EQUAL(a, b, digits) (! NN_Cmp (a, b, digits))
#define NN_EVEN(a, digits) (((digits) == 0) || ! (a[0] & 1))

143
lib/rsaref/prime.c Normal file
View file

@ -0,0 +1,143 @@
/* PRIME.C - primality-testing routines
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
#include "global.h"
#include "rsaref.h"
#include "r_random.h"
#include "nn.h"
#include "prime.h"
static unsigned int SMALL_PRIMES[] = { 3, 5, 7, 11 };
#define SMALL_PRIME_COUNT 4
static int ProbablePrime PROTO_LIST ((NN_DIGIT *, unsigned int));
static int SmallFactor PROTO_LIST ((NN_DIGIT *, unsigned int));
static int FermatTest PROTO_LIST ((NN_DIGIT *, unsigned int));
/* Generates a probable prime a between b and c such that a-1 is
divisible by d.
Lengths: a[digits], b[digits], c[digits], d[digits].
Assumes b < c, digits < MAX_NN_DIGITS.
Returns RE_NEED_RANDOM if randomStruct not seeded, RE_DATA if
unsuccessful.
*/
int GeneratePrime (a, b, c, d, digits, randomStruct)
NN_DIGIT *a, *b, *c, *d;
unsigned int digits;
R_RANDOM_STRUCT *randomStruct;
{
int status;
unsigned char block[MAX_NN_DIGITS * NN_DIGIT_LEN];
NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS];
/* Generate random number between b and c.
*/
if ((status = R_GenerateBytes (block, digits * NN_DIGIT_LEN, randomStruct)))
return (status);
NN_Decode (a, digits, block, digits * NN_DIGIT_LEN);
NN_Sub (t, c, b, digits);
NN_ASSIGN_DIGIT (u, 1, digits);
NN_Add (t, t, u, digits);
NN_Mod (a, a, digits, t, digits);
NN_Add (a, a, b, digits);
/* Adjust so that a-1 is divisible by d.
*/
NN_Mod (t, a, digits, d, digits);
NN_Sub (a, a, t, digits);
NN_Add (a, a, u, digits);
if (NN_Cmp (a, b, digits) < 0)
NN_Add (a, a, d, digits);
if (NN_Cmp (a, c, digits) > 0)
NN_Sub (a, a, d, digits);
/* Search to c in steps of d.
*/
NN_Assign (t, c, digits);
NN_Sub (t, t, d, digits);
while (! ProbablePrime (a, digits)) {
if (NN_Cmp (a, t, digits) > 0)
return (RE_DATA);
NN_Add (a, a, d, digits);
}
return (0);
}
/* Returns nonzero iff a is a probable prime.
Lengths: a[aDigits].
Assumes aDigits < MAX_NN_DIGITS.
*/
static int ProbablePrime (a, aDigits)
NN_DIGIT *a;
unsigned int aDigits;
{
return (! SmallFactor (a, aDigits) && FermatTest (a, aDigits));
}
/* Returns nonzero iff a has a prime factor in SMALL_PRIMES.
Lengths: a[aDigits].
Assumes aDigits < MAX_NN_DIGITS.
*/
static int SmallFactor (a, aDigits)
NN_DIGIT *a;
unsigned int aDigits;
{
int status;
NN_DIGIT t[1];
unsigned int i;
status = 0;
for (i = 0; i < SMALL_PRIME_COUNT; i++) {
NN_ASSIGN_DIGIT (t, SMALL_PRIMES[i], 1);
if ((aDigits == 1) && ! NN_Cmp (a, t, 1))
break;
NN_Mod (t, a, aDigits, t, 1);
if (NN_Zero (t, 1)) {
status = 1;
break;
}
}
/* Zeroize sensitive information.
*/
i = 0;
R_memset ((POINTER)t, 0, sizeof (t));
return (status);
}
/* Returns nonzero iff a passes Fermat's test for witness 2.
(All primes pass the test, and nearly all composites fail.)
Lengths: a[aDigits].
Assumes aDigits < MAX_NN_DIGITS.
*/
static int FermatTest (a, aDigits)
NN_DIGIT *a;
unsigned int aDigits;
{
int status;
NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS];
NN_ASSIGN_DIGIT (t, 2, aDigits);
NN_ModExp (u, t, a, aDigits, a, aDigits);
status = NN_EQUAL (t, u, aDigits);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)u, 0, sizeof (u));
return (status);
}

10
lib/rsaref/prime.h Normal file
View file

@ -0,0 +1,10 @@
/* PRIME.H - header file for PRIME.C
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
int GeneratePrime PROTO_LIST
((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int,
R_RANDOM_STRUCT *));

145
lib/rsaref/r_dh.c Normal file
View file

@ -0,0 +1,145 @@
/* R_DH.C - Diffie-Hellman routines for RSAREF
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1993. All rights reserved.
*/
#include "global.h"
#include "rsaref.h"
#include "r_random.h"
#include "nn.h"
#include "prime.h"
/* Generates Diffie-Hellman parameters.
*/
int R_GenerateDHParams (params, primeBits, subPrimeBits, randomStruct)
R_DH_PARAMS *params; /* new Diffie-Hellman parameters */
unsigned int primeBits; /* length of prime in bits */
unsigned int subPrimeBits; /* length of subprime in bits */
R_RANDOM_STRUCT *randomStruct; /* random structure */
{
int status;
NN_DIGIT g[MAX_NN_DIGITS], p[MAX_NN_DIGITS], q[MAX_NN_DIGITS],
t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS];
unsigned int pDigits;
pDigits = (primeBits + NN_DIGIT_BITS - 1) / NN_DIGIT_BITS;
/* Generate subprime q between 2^(subPrimeBits-1) and
2^subPrimeBits-1, searching in steps of 2.
*/
NN_Assign2Exp (t, subPrimeBits-1, pDigits);
NN_Assign (u, t, pDigits);
NN_ASSIGN_DIGIT (v, 1, pDigits);
NN_Sub (v, t, v, pDigits);
NN_Add (u, u, v, pDigits);
NN_ASSIGN_DIGIT (v, 2, pDigits);
if ((status = GeneratePrime (q, t, u, v, pDigits, randomStruct)))
return (status);
/* Generate prime p between 2^(primeBits-1) and 2^primeBits-1,
searching in steps of 2*q.
*/
NN_Assign2Exp (t, primeBits-1, pDigits);
NN_Assign (u, t, pDigits);
NN_ASSIGN_DIGIT (v, 1, pDigits);
NN_Sub (v, t, v, pDigits);
NN_Add (u, u, v, pDigits);
NN_LShift (v, q, 1, pDigits);
if ((status = GeneratePrime (p, t, u, v, pDigits, randomStruct)))
return (status);
/* Generate generator g for subgroup as 2^((p-1)/q) mod p.
*/
NN_ASSIGN_DIGIT (g, 2, pDigits);
NN_Div (t, u, p, pDigits, q, pDigits);
NN_ModExp (g, g, t, pDigits, p, pDigits);
params->generatorLen = params->primeLen = DH_PRIME_LEN (primeBits);
NN_Encode (params->prime, params->primeLen, p, pDigits);
NN_Encode (params->generator, params->generatorLen, g, pDigits);
return (0);
}
/* Sets up Diffie-Hellman key agreement. Public value has same length
as prime.
*/
int R_SetupDHAgreement
(publicValue, privateValue, privateValueLen, params, randomStruct)
unsigned char *publicValue; /* new public value */
unsigned char *privateValue; /* new private value */
unsigned int privateValueLen; /* length of private value */
R_DH_PARAMS *params; /* Diffie-Hellman parameters */
R_RANDOM_STRUCT *randomStruct; /* random structure */
{
int status;
NN_DIGIT g[MAX_NN_DIGITS], p[MAX_NN_DIGITS], x[MAX_NN_DIGITS],
y[MAX_NN_DIGITS];
unsigned int pDigits, xDigits;
NN_Decode (p, MAX_NN_DIGITS, params->prime, params->primeLen);
pDigits = NN_Digits (p, MAX_NN_DIGITS);
NN_Decode (g, pDigits, params->generator, params->generatorLen);
/* Generate private value.
*/
if ((status = R_GenerateBytes (privateValue, privateValueLen, randomStruct)))
return (status);
NN_Decode (x, pDigits, privateValue, privateValueLen);
xDigits = NN_Digits (x, pDigits);
/* Compute y = g^x mod p.
*/
NN_ModExp (y, g, x, xDigits, p, pDigits);
NN_Encode (publicValue, params->primeLen, y, pDigits);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)x, 0, sizeof (x));
return (0);
}
/* Computes agreed key from the other party's public value, a private
value, and Diffie-Hellman parameters. Other public value and
agreed-upon key have same length as prime.
Requires otherPublicValue < prime.
*/
int R_ComputeDHAgreedKey
(agreedKey, otherPublicValue, privateValue, privateValueLen, params)
unsigned char *agreedKey; /* new agreed key */
unsigned char *otherPublicValue; /* other's public value */
unsigned char *privateValue; /* private value */
unsigned int privateValueLen; /* length of private value */
R_DH_PARAMS *params; /* Diffie-Hellman parameters */
{
NN_DIGIT p[MAX_NN_DIGITS], x[MAX_NN_DIGITS], y[MAX_NN_DIGITS],
z[MAX_NN_DIGITS];
unsigned int pDigits, xDigits;
NN_Decode (p, MAX_NN_DIGITS, params->prime, params->primeLen);
pDigits = NN_Digits (p, MAX_NN_DIGITS);
NN_Decode (x, pDigits, privateValue, privateValueLen);
xDigits = NN_Digits (x, pDigits);
NN_Decode (y, pDigits, otherPublicValue, params->primeLen);
if (NN_Cmp (y, p, pDigits) >= 0)
return (RE_DATA);
/* Compute z = y^x mod p.
*/
NN_ModExp (z, y, x, xDigits, p, pDigits);
NN_Encode (agreedKey, params->primeLen, z, pDigits);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)x, 0, sizeof (x));
R_memset ((POINTER)z, 0, sizeof (z));
return (0);
}

262
lib/rsaref/r_encode.c Normal file
View file

@ -0,0 +1,262 @@
/* R_ENCODE.C - RFC 1113 encoding and decoding routines
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
#include "global.h"
#include "rsaref.h"
/* RFC 1113 encoding:
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
*/
#define ENCODING(i) \
(unsigned char)(((i) < 26) ? ((i) + 0x41) : \
(((i) < 52) ? ((i) - 26 + 0x61) : \
(((i) < 62) ? ((i) - 52 + 0x30) : \
(((i) == 62) ? 0x2b : 0x2f))))
#define ENCODING_PAD 0x3d
#define IS_ENCODING(c) \
((((c) >= 0x41) && ((c) <= 0x5a)) || \
(((c) >= 0x61) && ((c) <= 0x7a)) || \
(((c) >= 0x30) && ((c) <= 0x39)) || \
((c) == 0x2b) || \
((c) == 0x2f))
/* assumes IS_ENCODING (c) == 1 */
#define DECODING(c) \
(((c) == 0x2b) ? 62 : \
(((c) == 0x2f) ? 63 : \
(((c) <= 0x39) ? ((c) - 0x30 + 52) : \
(((c) <= 0x5a) ? ((c) - 0x41) : ((c) - 0x61 + 26)))))
static void EncodeQuantum PROTO_LIST ((unsigned char [4], unsigned char [3]));
static int DecodeQuantum PROTO_LIST ((unsigned char [3], unsigned char [4]));
static void EncodeLastQuantum
PROTO_LIST ((unsigned char [4], unsigned char *, unsigned int));
static int DecodeLastQuantum
PROTO_LIST ((unsigned char *, unsigned int *, unsigned char [4]));
/* This always returns 0. It is an int function for future compatibility.
*/
int R_EncodePEMBlock (encodedBlock, encodedBlockLen, block, blockLen)
unsigned char *encodedBlock; /* encoded block */
unsigned int *encodedBlockLen; /* length of encoded block */
unsigned char *block; /* block */
unsigned int blockLen; /* length of block */
{
unsigned int i, lastLen;
if (blockLen < 1) {
*encodedBlockLen = 0;
return (0);
}
for (i = 0; i < (blockLen-1)/3; i++)
EncodeQuantum (&encodedBlock[4*i], &block[3*i]);
lastLen = blockLen - 3*i;
EncodeLastQuantum (&encodedBlock[4*i], &block[3*i], lastLen);
*encodedBlockLen = 4*i + 4;
return (0);
}
int R_DecodePEMBlock (block, blockLen, encodedBlock, encodedBlockLen)
unsigned char *block; /* block */
unsigned int *blockLen; /* length of block */
unsigned char *encodedBlock; /* encoded block */
unsigned int encodedBlockLen; /* length of encoded block */
{
int status;
unsigned int i, lastLen;
if (encodedBlockLen % 4)
return (RE_ENCODING);
if (encodedBlockLen < 1) {
*blockLen = 0;
return (0);
}
for (i = 0; i < (encodedBlockLen-1)/4; i++)
if ((status = DecodeQuantum (&block[3*i], &encodedBlock[4*i])))
return (status);
if ((status = DecodeLastQuantum (&block[3*i], &lastLen, &encodedBlock[4*i])))
return (status);
*blockLen = 3*i + lastLen;
return (0);
}
static void EncodeQuantum (encodedQuantum, quantum)
unsigned char encodedQuantum[4];
unsigned char quantum[3];
{
UINT4 temp;
unsigned int a, b, c, d;
temp = ((UINT4)quantum[0]) << 16;
temp |= ((UINT4)quantum[1]) << 8;
temp |= (UINT4)quantum[2];
a = (unsigned int)((temp >> 18) & 0x3f);
b = (unsigned int)((temp >> 12) & 0x3f);
c = (unsigned int)((temp >> 6) & 0x3f);
d = (unsigned int)(temp & 0x3f);
encodedQuantum[0] = ENCODING (a);
encodedQuantum[1] = ENCODING (b);
encodedQuantum[2] = ENCODING (c);
encodedQuantum[3] = ENCODING (d);
/* Zeroize potentially sensitive information.
*/
temp = 0;
a = b = c = d = 0;
}
static int DecodeQuantum (quantum, encodedQuantum)
unsigned char quantum[3];
unsigned char encodedQuantum[4];
{
UINT4 temp;
unsigned int a, b, c, d;
if (! IS_ENCODING (encodedQuantum[0]) ||
! IS_ENCODING (encodedQuantum[1]) ||
! IS_ENCODING (encodedQuantum[2]) ||
! IS_ENCODING (encodedQuantum[3]))
return (RE_ENCODING);
a = DECODING (encodedQuantum[0]);
b = DECODING (encodedQuantum[1]);
c = DECODING (encodedQuantum[2]);
d = DECODING (encodedQuantum[3]);
temp = ((UINT4)a) << 18;
temp |= ((UINT4)b) << 12;
temp |= ((UINT4)c) << 6;
temp |= (UINT4)d;
quantum[0] = (unsigned char)(temp >> 16);
quantum[1] = (unsigned char)(temp >> 8);
quantum[2] = (unsigned char)temp;
/* Zeroize potentially sensitive information.
*/
temp = 0;
a = b = c = d = 0;
return (0);
}
static void EncodeLastQuantum (encodedQuantum, quantum, quantumLen)
unsigned char encodedQuantum[4];
unsigned char *quantum;
unsigned int quantumLen; /* 1, 2 or 3 */
{
UINT4 temp;
unsigned int a, b, c = 0, d = 0;
temp = ((UINT4)quantum[0]) << 16;
if (quantumLen >= 2)
temp |= ((UINT4)quantum[1]) << 8;
if (quantumLen == 3)
temp |= ((UINT4)quantum[2]);
a = (unsigned int)((temp >> 18) & 0x3f);
b = (unsigned int)((temp >> 12) & 0x3f);
if (quantumLen >= 2)
c = (unsigned int)((temp >> 6) & 0x3f);
if (quantumLen == 3)
d = (unsigned int)(temp & 0x3f);
encodedQuantum[0] = ENCODING (a);
encodedQuantum[1] = ENCODING (b);
if (quantumLen >= 2)
encodedQuantum[2] = ENCODING (c);
else
encodedQuantum[2] = ENCODING_PAD;
if (quantumLen == 3)
encodedQuantum[3] = ENCODING (d);
else
encodedQuantum[3] = ENCODING_PAD;
/* Zeroize potentially sensitive information.
*/
temp = 0;
a = b = c = d = 0;
}
static int DecodeLastQuantum (quantum, quantumLen, encodedQuantum)
unsigned char *quantum;
unsigned int *quantumLen; /* 1, 2 or 3 */
unsigned char encodedQuantum[4];
{
UINT4 temp;
unsigned int a, b, c = 0, d = 0;
if (! IS_ENCODING (encodedQuantum[0]) ||
! IS_ENCODING (encodedQuantum[1]) ||
(! IS_ENCODING (encodedQuantum[2]) &&
(encodedQuantum[2] != ENCODING_PAD)) ||
(! IS_ENCODING (encodedQuantum[3]) &&
(encodedQuantum[3] != ENCODING_PAD)))
return (RE_ENCODING);
if (encodedQuantum[2] == ENCODING_PAD)
*quantumLen = 1;
else if (encodedQuantum[3] == ENCODING_PAD)
*quantumLen = 2;
else
*quantumLen = 3;
a = DECODING (encodedQuantum[0]);
b = DECODING (encodedQuantum[1]);
if (*quantumLen >= 2)
c = DECODING (encodedQuantum[2]);
if (*quantumLen == 3)
d = DECODING (encodedQuantum[3]);
temp = ((UINT4)a) << 18;
temp |= ((UINT4)b) << 12;
if (*quantumLen >= 2)
temp |= ((UINT4)c) << 6;
if (*quantumLen == 3)
temp |= ((UINT4)d);
quantum[0] = (unsigned char)(temp >> 16);
if (*quantumLen >= 2)
quantum[1] = (unsigned char)(temp >> 8);
if (*quantumLen == 3)
quantum[2] = (unsigned char)temp;
/* Zeroize potentially sensitive information.
*/
temp = 0;
a = b = c = d = 0;
return (0);
}

965
lib/rsaref/r_enhanc.c Normal file
View file

@ -0,0 +1,965 @@
/* R_ENHANC.C - cryptographic enhancements for RSAREF
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
#include "global.h"
#include "rsaref.h"
#include "r_random.h"
#include "rsa.h"
/* DigestInfo encoding is DIGEST_INFO_A, then 2 or 5 (for MD2/MD5),
then DIGEST_INFO_B, then 16-byte message digest.
*/
static unsigned char DIGEST_INFO_A[] = {
0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x02
};
#define DIGEST_INFO_A_LEN sizeof (DIGEST_INFO_A)
static unsigned char DIGEST_INFO_B[] = { 0x05, 0x00, 0x04, 0x10 };
#define DIGEST_INFO_B_LEN sizeof (DIGEST_INFO_B)
#define DIGEST_INFO_LEN (DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN + 16)
static unsigned char *PADDING[] = {
(unsigned char *)"", (unsigned char *)"\001", (unsigned char *)"\002\002",
(unsigned char *)"\003\003\003", (unsigned char *)"\004\004\004\004",
(unsigned char *)"\005\005\005\005\005",
(unsigned char *)"\006\006\006\006\006\006",
(unsigned char *)"\007\007\007\007\007\007\007",
(unsigned char *)"\010\010\010\010\010\010\010\010"
};
#define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN
static void R_EncodeDigestInfo PROTO_LIST
((unsigned char *, int, unsigned char *));
static void EncryptPEMUpdateFinal PROTO_LIST
((R_ENVELOPE_CTX *, unsigned char *, unsigned int *, unsigned char *,
unsigned int));
static int DecryptPEMUpdateFinal PROTO_LIST
((R_ENVELOPE_CTX *, unsigned char *, unsigned int *, unsigned char *,
unsigned int));
static int CipherInit PROTO_LIST
((R_ENVELOPE_CTX *, int, unsigned char *, unsigned char *, int));
static void CipherUpdate PROTO_LIST
((R_ENVELOPE_CTX *, unsigned char *, unsigned char *, unsigned int));
static void CipherRestart PROTO_LIST ((R_ENVELOPE_CTX *));
int R_DigestInit (context, digestAlgorithm)
R_DIGEST_CTX *context; /* new context */
int digestAlgorithm; /* message-digest algorithm */
{
context->digestAlgorithm = digestAlgorithm;
switch (digestAlgorithm) {
case DA_MD2:
MD2Init (&context->context.md2);
break;
case DA_MD5:
MD5Init (&context->context.md5);
break;
default:
return (RE_DIGEST_ALGORITHM);
}
return (0);
}
int R_DigestUpdate (context, partIn, partInLen)
R_DIGEST_CTX *context; /* context */
unsigned char *partIn; /* next data part */
unsigned int partInLen; /* length of next data part */
{
if (context->digestAlgorithm == DA_MD2)
MD2Update (&context->context.md2, partIn, partInLen);
else
MD5Update (&context->context.md5, partIn, partInLen);
return (0);
}
int R_DigestFinal (context, digest, digestLen)
R_DIGEST_CTX *context; /* context */
unsigned char *digest; /* message digest */
unsigned int *digestLen; /* length of message digest */
{
*digestLen = 16;
if (context->digestAlgorithm == DA_MD2)
MD2Final (digest, &context->context.md2);
else
MD5Final (digest, &context->context.md5);
return (0);
}
int R_SignInit (context, digestAlgorithm)
R_SIGNATURE_CTX *context; /* new context */
int digestAlgorithm; /* message-digest algorithm */
{
return (R_DigestInit (&context->digestContext, digestAlgorithm));
}
int R_SignUpdate (context, partIn, partInLen)
R_SIGNATURE_CTX *context; /* context */
unsigned char *partIn; /* next data part */
unsigned int partInLen; /* length of next data part */
{
return (R_DigestUpdate (&context->digestContext, partIn, partInLen));
}
int R_SignFinal (context, signature, signatureLen, privateKey)
R_SIGNATURE_CTX *context; /* context */
unsigned char *signature; /* signature */
unsigned int *signatureLen; /* length of signature */
R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */
{
int status;
unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN];
unsigned int digestLen;
do {
if ((status = R_DigestFinal (&context->digestContext, digest, &digestLen))
!= 0)
break;
R_EncodeDigestInfo
(digestInfo, context->digestContext.digestAlgorithm, digest);
if (RSAPrivateEncrypt
(signature, signatureLen, digestInfo, DIGEST_INFO_LEN, privateKey)
!= 0) {
status = RE_PRIVATE_KEY;
break;
}
/* Reset for another verification. Assume Init won't fail */
R_DigestInit
(&context->digestContext, context->digestContext.digestAlgorithm);
} while (0);
/* Zeroize potentially sensitive information.
*/
R_memset ((POINTER)digest, 0, sizeof (digest));
R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo));
return (status);
}
int R_VerifyInit (context, digestAlgorithm)
R_SIGNATURE_CTX *context; /* new context */
int digestAlgorithm; /* message-digest algorithm */
{
return (R_DigestInit (&context->digestContext, digestAlgorithm));
}
int R_VerifyUpdate (context, partIn, partInLen)
R_SIGNATURE_CTX *context; /* context */
unsigned char *partIn; /* next data part */
unsigned int partInLen; /* length of next data part */
{
return (R_DigestUpdate (&context->digestContext, partIn, partInLen));
}
int R_VerifyFinal (context, signature, signatureLen, publicKey)
R_SIGNATURE_CTX *context; /* context */
unsigned char *signature; /* signature */
unsigned int signatureLen; /* length of signature */
R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */
{
int status;
unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN],
originalDigestInfo[MAX_SIGNATURE_LEN];
unsigned int originalDigestInfoLen, digestLen;
if (signatureLen > MAX_SIGNATURE_LEN)
return (RE_LEN);
status = 0;
do {
if ((status = R_DigestFinal (&context->digestContext, digest, &digestLen))
!= 0)
break;
R_EncodeDigestInfo
(digestInfo, context->digestContext.digestAlgorithm, digest);
if (RSAPublicDecrypt
(originalDigestInfo, &originalDigestInfoLen, signature, signatureLen,
publicKey) != 0) {
status = RE_PUBLIC_KEY;
break;
}
if ((originalDigestInfoLen != DIGEST_INFO_LEN) ||
(R_memcmp
((POINTER)originalDigestInfo, (POINTER)digestInfo,
DIGEST_INFO_LEN))) {
status = RE_SIGNATURE;
break;
}
/* Reset for another verification. Assume Init won't fail */
R_DigestInit
(&context->digestContext, context->digestContext.digestAlgorithm);
} while (0);
/* Zeroize potentially sensitive information.
*/
R_memset ((POINTER)digest, 0, sizeof (digest));
R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo));
R_memset ((POINTER)originalDigestInfo, 0, sizeof (originalDigestInfo));
return (status);
}
/* Caller must ASCII recode the encrypted keys if desired.
*/
int R_SealInit
(context, encryptedKeys, encryptedKeyLens, iv, publicKeyCount, publicKeys,
encryptionAlgorithm, randomStruct)
R_ENVELOPE_CTX *context; /* new context */
unsigned char **encryptedKeys; /* encrypted keys */
unsigned int *encryptedKeyLens; /* lengths of encrypted keys */
unsigned char iv[8]; /* initialization vector */
unsigned int publicKeyCount; /* number of public keys */
R_RSA_PUBLIC_KEY **publicKeys; /* public keys */
int encryptionAlgorithm; /* data encryption algorithm */
R_RANDOM_STRUCT *randomStruct; /* random structure */
{
int status;
unsigned char key[24];
unsigned int keyLen, i;
do {
context->encryptionAlgorithm = encryptionAlgorithm;
keyLen = (encryptionAlgorithm == EA_DES_CBC) ? 8 : 24;
if ((status = R_GenerateBytes (key, keyLen, randomStruct)) != 0)
break;
if ((status = R_GenerateBytes (iv, 8, randomStruct)) != 0)
break;
if (encryptionAlgorithm == EA_DES_EDE2_CBC)
/* Make both E keys the same */
R_memcpy ((POINTER)(key + 16), (POINTER)key, 8);
if ((status = CipherInit (context, encryptionAlgorithm, key, iv, 1)) != 0)
break;
for (i = 0; i < publicKeyCount; ++i) {
if (RSAPublicEncrypt
(encryptedKeys[i], &encryptedKeyLens[i], key, keyLen,
publicKeys[i], randomStruct)) {
status = RE_PUBLIC_KEY;
break;
}
}
if (status != 0)
break;
context->bufferLen = 0;
} while (0);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)key, 0, sizeof (key));
return (status);
}
/* Assume partOut buffer is at least partInLen + 7, since this may flush
buffered input.
*/
int R_SealUpdate (context, partOut, partOutLen, partIn, partInLen)
R_ENVELOPE_CTX *context; /* context */
unsigned char *partOut; /* next encrypted data part */
unsigned int *partOutLen; /* length of next encrypted data part */
unsigned char *partIn; /* next data part */
unsigned int partInLen; /* length of next data part */
{
unsigned int tempLen;
tempLen = 8 - context->bufferLen;
if (partInLen < tempLen) {
/* Just accumulate into buffer.
*/
R_memcpy
((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
partInLen);
context->bufferLen += partInLen;
*partOutLen = 0;
return (0);
}
/* Fill the buffer and encrypt.
*/
R_memcpy
((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
tempLen);
CipherUpdate (context, partOut, context->buffer, 8);
partIn += tempLen;
partInLen -= tempLen;
partOut += 8;
*partOutLen = 8;
/* Encrypt as many 8-byte blocks as possible.
*/
tempLen = 8 * (partInLen / 8);
CipherUpdate (context, partOut, partIn, tempLen);
partIn += tempLen;
partInLen -= tempLen;
*partOutLen += tempLen;
/* Length is now less than 8, so copy remainder to buffer.
*/
R_memcpy
((POINTER)context->buffer, (POINTER)partIn,
context->bufferLen = partInLen);
return (0);
}
/* Assume partOut buffer is at least 8 bytes.
*/
int R_SealFinal (context, partOut, partOutLen)
R_ENVELOPE_CTX *context; /* context */
unsigned char *partOut; /* last encrypted data part */
unsigned int *partOutLen; /* length of last encrypted data part */
{
unsigned int padLen;
/* Pad and encrypt final block.
*/
padLen = 8 - context->bufferLen;
R_memset
((POINTER)(context->buffer + context->bufferLen), (int)padLen, padLen);
CipherUpdate (context, partOut, context->buffer, 8);
*partOutLen = 8;
/* Restart the context.
*/
CipherRestart (context);
context->bufferLen = 0;
return (0);
}
/* Assume caller has already ASCII decoded the encryptedKey if necessary.
*/
int R_OpenInit
(context, encryptionAlgorithm, encryptedKey, encryptedKeyLen, iv, privateKey)
R_ENVELOPE_CTX *context; /* new context */
int encryptionAlgorithm; /* data encryption algorithm */
unsigned char *encryptedKey; /* encrypted data encryption key */
unsigned int encryptedKeyLen; /* length of encrypted key */
unsigned char iv[8]; /* initialization vector */
R_RSA_PRIVATE_KEY *privateKey; /* recipient's RSA private key */
{
int status;
unsigned char key[MAX_ENCRYPTED_KEY_LEN];
unsigned int keyLen;
if (encryptedKeyLen > MAX_ENCRYPTED_KEY_LEN)
return (RE_LEN);
do {
context->encryptionAlgorithm = encryptionAlgorithm;
if (RSAPrivateDecrypt
(key, &keyLen, encryptedKey, encryptedKeyLen, privateKey)) {
status = RE_PRIVATE_KEY;
break;
}
if (encryptionAlgorithm == EA_DES_CBC) {
if (keyLen != 8) {
status = RE_PRIVATE_KEY;
break;
}
}
else {
if (keyLen != 24) {
status = RE_PRIVATE_KEY;
break;
}
}
if ((status = CipherInit (context, encryptionAlgorithm, key, iv, 0)) != 0)
break;
context->bufferLen = 0;
} while (0);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)key, 0, sizeof (key));
return (status);
}
/* Assume partOut buffer is at least partInLen + 7, since this may flush
buffered input. Always leaves at least one byte in buffer.
*/
int R_OpenUpdate (context, partOut, partOutLen, partIn, partInLen)
R_ENVELOPE_CTX *context; /* context */
unsigned char *partOut; /* next recovered data part */
unsigned int *partOutLen; /* length of next recovered data part */
unsigned char *partIn; /* next encrypted data part */
unsigned int partInLen; /* length of next encrypted data part */
{
unsigned int tempLen;
tempLen = 8 - context->bufferLen;
if (partInLen <= tempLen) {
/* Just accumulate into buffer.
*/
R_memcpy
((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
partInLen);
context->bufferLen += partInLen;
*partOutLen = 0;
return (0);
}
/* Fill the buffer and decrypt. We know that there will be more left
in partIn after decrypting the buffer.
*/
R_memcpy
((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
tempLen);
CipherUpdate (context, partOut, context->buffer, 8);
partIn += tempLen;
partInLen -= tempLen;
partOut += 8;
*partOutLen = 8;
/* Decrypt as many 8 byte blocks as possible, leaving at least one byte
in partIn.
*/
tempLen = 8 * ((partInLen - 1) / 8);
CipherUpdate (context, partOut, partIn, tempLen);
partIn += tempLen;
partInLen -= tempLen;
*partOutLen += tempLen;
/* Length is between 1 and 8, so copy into buffer.
*/
R_memcpy
((POINTER)context->buffer, (POINTER)partIn,
context->bufferLen = partInLen);
return (0);
}
/* Assume partOut buffer is at least 7 bytes.
*/
int R_OpenFinal (context, partOut, partOutLen)
R_ENVELOPE_CTX *context; /* context */
unsigned char *partOut; /* last recovered data part */
unsigned int *partOutLen; /* length of last recovered data part */
{
int status;
unsigned char lastPart[8];
unsigned int padLen;
status = 0;
do {
if (context->bufferLen == 0)
/* There was no input data to decrypt */
*partOutLen = 0;
else {
if (context->bufferLen != 8) {
status = RE_KEY;
break;
}
/* Decrypt and strip padding from final block which is in buffer.
*/
CipherUpdate (context, lastPart, context->buffer, 8);
padLen = lastPart[7];
if (padLen == 0 || padLen > 8) {
status = RE_KEY;
break;
}
if (R_memcmp
((POINTER)&lastPart[8 - padLen], PADDING[padLen], padLen) != 0) {
status = RE_KEY;
break;
}
R_memcpy ((POINTER)partOut, (POINTER)lastPart, *partOutLen = 8 - padLen);
}
/* Restart the context.
*/
CipherRestart (context);
context->bufferLen = 0;
} while (0);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)lastPart, 0, sizeof (lastPart));
return (status);
}
int R_SignPEMBlock
(encodedContent, encodedContentLen, encodedSignature, encodedSignatureLen,
content, contentLen, recode, digestAlgorithm, privateKey)
unsigned char *encodedContent; /* encoded content */
unsigned int *encodedContentLen; /* length of encoded content */
unsigned char *encodedSignature; /* encoded signature */
unsigned int *encodedSignatureLen; /* length of encoded signature */
unsigned char *content; /* content */
unsigned int contentLen; /* length of content */
int recode; /* recoding flag */
int digestAlgorithm; /* message-digest algorithm */
R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */
{
int status;
unsigned char signature[MAX_SIGNATURE_LEN];
unsigned int signatureLen;
if ((status = R_SignBlock
(signature, &signatureLen, content, contentLen, digestAlgorithm,
privateKey)) != 0)
return (status);
R_EncodePEMBlock
(encodedSignature, encodedSignatureLen, signature, signatureLen);
if (recode)
R_EncodePEMBlock
(encodedContent, encodedContentLen, content, contentLen);
return (0);
}
int R_SignBlock
(signature, signatureLen, block, blockLen, digestAlgorithm, privateKey)
unsigned char *signature; /* signature */
unsigned int *signatureLen; /* length of signature */
unsigned char *block; /* block */
unsigned int blockLen; /* length of block */
int digestAlgorithm; /* message-digest algorithm */
R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */
{
R_SIGNATURE_CTX context;
int status;
do {
if ((status = R_SignInit (&context, digestAlgorithm)) != 0)
break;
if ((status = R_SignUpdate (&context, block, blockLen)) != 0)
break;
if ((status = R_SignFinal (&context, signature, signatureLen, privateKey))
!= 0)
break;
} while (0);
/* Zeroize sensitive information. */
R_memset ((POINTER)&context, 0, sizeof (context));
return (status);
}
int R_VerifyPEMSignature
(content, contentLen, encodedContent, encodedContentLen, encodedSignature,
encodedSignatureLen, recode, digestAlgorithm, publicKey)
unsigned char *content; /* content */
unsigned int *contentLen; /* length of content */
unsigned char *encodedContent; /* (possibly) encoded content */
unsigned int encodedContentLen; /* length of encoded content */
unsigned char *encodedSignature; /* encoded signature */
unsigned int encodedSignatureLen; /* length of encoded signature */
int recode; /* recoding flag */
int digestAlgorithm; /* message-digest algorithm */
R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */
{
unsigned char signature[MAX_SIGNATURE_LEN];
unsigned int signatureLen;
if (encodedSignatureLen > MAX_PEM_SIGNATURE_LEN)
return (RE_SIGNATURE_ENCODING);
if (recode) {
if (R_DecodePEMBlock
(content, contentLen, encodedContent, encodedContentLen))
return (RE_CONTENT_ENCODING);
}
else {
content = encodedContent;
*contentLen = encodedContentLen;
}
if (R_DecodePEMBlock
(signature, &signatureLen, encodedSignature, encodedSignatureLen))
return (RE_SIGNATURE_ENCODING);
return (R_VerifyBlockSignature
(content, *contentLen, signature, signatureLen, digestAlgorithm,
publicKey));
}
int R_VerifyBlockSignature
(block, blockLen, signature, signatureLen, digestAlgorithm, publicKey)
unsigned char *block; /* block */
unsigned int blockLen; /* length of block */
unsigned char *signature; /* signature */
unsigned int signatureLen; /* length of signature */
int digestAlgorithm; /* message-digest algorithm */
R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */
{
R_SIGNATURE_CTX context;
int status;
do {
if ((status = R_VerifyInit (&context, digestAlgorithm)) != 0)
break;
if ((status = R_VerifyUpdate (&context, block, blockLen)) != 0)
break;
if ((status = R_VerifyFinal (&context, signature, signatureLen, publicKey))
!= 0)
break;
} while (0);
/* Zeroize sensitive information. */
R_memset ((POINTER)&context, 0, sizeof (context));
return (status);
}
int R_SealPEMBlock
(encryptedContent, encryptedContentLen, encryptedKey, encryptedKeyLen,
encryptedSignature, encryptedSignatureLen, iv, content, contentLen,
digestAlgorithm, publicKey, privateKey, randomStruct)
unsigned char *encryptedContent; /* encoded, encrypted content */
unsigned int *encryptedContentLen; /* length */
unsigned char *encryptedKey; /* encoded, encrypted key */
unsigned int *encryptedKeyLen; /* length */
unsigned char *encryptedSignature; /* encoded, encrypted signature */
unsigned int *encryptedSignatureLen; /* length */
unsigned char iv[8]; /* DES initialization vector */
unsigned char *content; /* content */
unsigned int contentLen; /* length of content */
int digestAlgorithm; /* message-digest algorithms */
R_RSA_PUBLIC_KEY *publicKey; /* recipient's RSA public key */
R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */
R_RANDOM_STRUCT *randomStruct; /* random structure */
{
R_ENVELOPE_CTX context;
R_RSA_PUBLIC_KEY *publicKeys[1];
int status;
unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN],
signature[MAX_SIGNATURE_LEN], *encryptedKeys[1];
unsigned int signatureLen, encryptedKeyBlockLen;
do {
if ((status = R_SignBlock
(signature, &signatureLen, content, contentLen, digestAlgorithm,
privateKey)) != 0)
break;
publicKeys[0] = publicKey;
encryptedKeys[0] = encryptedKeyBlock;
if ((status = R_SealInit
(&context, encryptedKeys, &encryptedKeyBlockLen, iv, 1, publicKeys,
EA_DES_CBC, randomStruct)) != 0)
break;
R_EncodePEMBlock
(encryptedKey, encryptedKeyLen, encryptedKeyBlock,
encryptedKeyBlockLen);
EncryptPEMUpdateFinal
(&context, encryptedContent, encryptedContentLen, content,
contentLen);
EncryptPEMUpdateFinal
(&context, encryptedSignature, encryptedSignatureLen, signature,
signatureLen);
} while (0);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)&context, 0, sizeof (context));
R_memset ((POINTER)signature, 0, sizeof (signature));
return (status);
}
int R_OpenPEMBlock
(content, contentLen, encryptedContent, encryptedContentLen, encryptedKey,
encryptedKeyLen, encryptedSignature, encryptedSignatureLen,
iv, digestAlgorithm, privateKey, publicKey)
unsigned char *content; /* content */
unsigned int *contentLen; /* length of content */
unsigned char *encryptedContent; /* encoded, encrypted content */
unsigned int encryptedContentLen; /* length */
unsigned char *encryptedKey; /* encoded, encrypted key */
unsigned int encryptedKeyLen; /* length */
unsigned char *encryptedSignature; /* encoded, encrypted signature */
unsigned int encryptedSignatureLen; /* length */
unsigned char iv[8]; /* DES initialization vector */
int digestAlgorithm; /* message-digest algorithms */
R_RSA_PRIVATE_KEY *privateKey; /* recipient's RSA private key */
R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */
{
R_ENVELOPE_CTX context;
int status;
unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN],
signature[MAX_SIGNATURE_LEN];
unsigned int encryptedKeyBlockLen, signatureLen;
if (encryptedKeyLen > MAX_PEM_ENCRYPTED_KEY_LEN)
return (RE_KEY_ENCODING);
if (encryptedSignatureLen > MAX_PEM_ENCRYPTED_SIGNATURE_LEN)
return (RE_SIGNATURE_ENCODING);
do {
if (R_DecodePEMBlock
(encryptedKeyBlock, &encryptedKeyBlockLen, encryptedKey,
encryptedKeyLen) != 0) {
status = RE_KEY_ENCODING;
break;
}
if ((status = R_OpenInit
(&context, EA_DES_CBC, encryptedKeyBlock, encryptedKeyBlockLen,
iv, privateKey)) != 0)
break;
if ((status = DecryptPEMUpdateFinal
(&context, content, contentLen, encryptedContent,
encryptedContentLen)) != 0) {
if ((status == RE_LEN || status == RE_ENCODING))
status = RE_CONTENT_ENCODING;
else
status = RE_KEY;
break;
}
if ((status = DecryptPEMUpdateFinal
(&context, signature, &signatureLen, encryptedSignature,
encryptedSignatureLen))) {
if ((status == RE_LEN || status == RE_ENCODING))
status = RE_SIGNATURE_ENCODING;
else
status = RE_KEY;
break;
}
if ((status = R_VerifyBlockSignature
(content, *contentLen, signature, signatureLen, digestAlgorithm,
publicKey)) != 0)
break;
} while (0);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)&context, 0, sizeof (context));
R_memset ((POINTER)signature, 0, sizeof (signature));
return (status);
}
int R_DigestBlock (digest, digestLen, block, blockLen, digestAlgorithm)
unsigned char *digest; /* message digest */
unsigned int *digestLen; /* length of message digest */
unsigned char *block; /* block */
unsigned int blockLen; /* length of block */
int digestAlgorithm; /* message-digest algorithm */
{
R_DIGEST_CTX context;
int status;
do {
if ((status = R_DigestInit (&context, digestAlgorithm)) != 0)
break;
if ((status = R_DigestUpdate (&context, block, blockLen)) != 0)
break;
if ((status = R_DigestFinal (&context, digest, digestLen)) != 0)
break;
} while (0);
/* Zeroize sensitive information. */
R_memset ((POINTER)&context, 0, sizeof (context));
return (status);
}
/* Assumes digestAlgorithm is DA_MD2 or DA_MD5 and digest length is 16.
*/
static void R_EncodeDigestInfo (digestInfo, digestAlgorithm, digest)
unsigned char *digestInfo; /* DigestInfo encoding */
int digestAlgorithm; /* message-digest algorithm */
unsigned char *digest; /* message digest */
{
R_memcpy
((POINTER)digestInfo, (POINTER)DIGEST_INFO_A, DIGEST_INFO_A_LEN);
digestInfo[DIGEST_INFO_A_LEN] =
(digestAlgorithm == DA_MD2) ? (unsigned char)2 : (unsigned char)5;
R_memcpy
((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1], (POINTER)DIGEST_INFO_B,
DIGEST_INFO_B_LEN);
R_memcpy
((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN],
(POINTER)digest, 16);
}
/* Call SealUpdate and SealFinal on the input and ASCII recode.
*/
static void EncryptPEMUpdateFinal
(context, output, outputLen, input, inputLen)
R_ENVELOPE_CTX *context;
unsigned char *output; /* encrypted, encoded block */
unsigned int *outputLen; /* length of output */
unsigned char *input; /* block to encrypt */
unsigned int inputLen; /* length */
{
unsigned char encryptedPart[24];
unsigned int i, lastPartLen, tempLen, len;
/* Choose a buffer size of 24 bytes to hold the temporary encrypted output
which will be encoded.
Encrypt and encode as many 24-byte blocks as possible.
*/
for (i = 0; i < inputLen / 24; ++i) {
/* Assume part out length will equal part in length since it is
a multiple of 8. Also assume no error output. */
R_SealUpdate (context, encryptedPart, &tempLen, &input[24*i], 24);
/* len is always 32 */
R_EncodePEMBlock (&output[32*i], &tempLen, encryptedPart, 24);
}
/* Encrypt the last part into encryptedPart.
*/
R_SealUpdate
(context, encryptedPart, &lastPartLen, &input[24*i], inputLen - 24*i);
R_SealFinal (context, encryptedPart + lastPartLen, &len);
lastPartLen += len;
R_EncodePEMBlock (&output[32*i], &len, encryptedPart, lastPartLen);
*outputLen = 32*i + len;
/* Zeroize sensitive information.
*/
R_memset ((POINTER)encryptedPart, 0, sizeof (encryptedPart));
}
static int DecryptPEMUpdateFinal (context, output, outputLen, input, inputLen)
R_ENVELOPE_CTX *context;
unsigned char *output; /* decoded, decrypted block */
unsigned int *outputLen; /* length of output */
unsigned char *input; /* encrypted, encoded block */
unsigned int inputLen; /* length */
{
int status = 0;
unsigned char encryptedPart[24];
unsigned int i, len;
do {
/* Choose a buffer size of 24 bytes to hold the temporary decoded output
which will be decrypted.
Decode and decrypt as many 32-byte input blocks as possible.
*/
*outputLen = 0;
for (i = 0; i < inputLen/32; i++) {
/* len is always 24 */
if ((status = R_DecodePEMBlock
(encryptedPart, &len, &input[32*i], 32)) != 0)
break;
/* Excpect no error return */
R_OpenUpdate (context, output, &len, encryptedPart, 24);
output += len;
*outputLen += len;
}
if (status)
break;
/* Decode the last part */
if ((status = R_DecodePEMBlock
(encryptedPart, &len, &input[32*i], inputLen - 32*i)) != 0)
break;
/* Decrypt the last part.
*/
R_OpenUpdate (context, output, &len, encryptedPart, len);
output += len;
*outputLen += len;
if ((status = R_OpenFinal (context, output, &len)) != 0)
break;
*outputLen += len;
} while (0);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)&context, 0, sizeof (context));
R_memset ((POINTER)encryptedPart, 0, sizeof (encryptedPart));
return (status);
}
static int CipherInit (context, encryptionAlgorithm, key, iv, encrypt)
R_ENVELOPE_CTX *context;
int encryptionAlgorithm;
unsigned char *key; /* DES key */
unsigned char *iv; /* DES initialization vector */
int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */
{
switch (encryptionAlgorithm) {
case EA_DES_CBC:
DES_CBCInit (&context->cipherContext.des, key, iv, encrypt);
return (0);
case EA_DESX_CBC:
DESX_CBCInit (&context->cipherContext.desx, key, iv, encrypt);
return (0);
case EA_DES_EDE2_CBC:
case EA_DES_EDE3_CBC:
DES3_CBCInit (&context->cipherContext.des3, key, iv, encrypt);
return (0);
default:
return (RE_ENCRYPTION_ALGORITHM);
}
}
/* Assume len is a multiple of 8.
*/
static void CipherUpdate (context, output, input, len)
R_ENVELOPE_CTX *context;
unsigned char *output; /* output block */
unsigned char *input; /* input block */
unsigned int len; /* length of input and output blocks */
{
if (context->encryptionAlgorithm == EA_DES_CBC)
DES_CBCUpdate (&context->cipherContext.des, output, input, len);
else if (context->encryptionAlgorithm == EA_DESX_CBC)
DESX_CBCUpdate (&context->cipherContext.desx, output, input, len);
else
DES3_CBCUpdate (&context->cipherContext.des3, output, input, len);
}
static void CipherRestart (context)
R_ENVELOPE_CTX *context;
{
if (context->encryptionAlgorithm == EA_DES_CBC)
DES_CBCRestart (&context->cipherContext.des);
else if (context->encryptionAlgorithm == EA_DESX_CBC)
DESX_CBCRestart (&context->cipherContext.desx);
else
DES3_CBCRestart (&context->cipherContext.des3);
}

182
lib/rsaref/r_keygen.c Normal file
View file

@ -0,0 +1,182 @@
/* R_KEYGEN.C - key-pair generation for RSAREF
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
#include "global.h"
#include "rsaref.h"
#include "r_random.h"
#include "nn.h"
#include "prime.h"
static int RSAFilter PROTO_LIST
((NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int));
static int RelativelyPrime PROTO_LIST
((NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int));
/* Generates an RSA key pair with a given length and public exponent.
*/
int R_GeneratePEMKeys (publicKey, privateKey, protoKey, randomStruct)
R_RSA_PUBLIC_KEY *publicKey; /* new RSA public key */
R_RSA_PRIVATE_KEY *privateKey; /* new RSA private key */
R_RSA_PROTO_KEY *protoKey; /* RSA prototype key */
R_RANDOM_STRUCT *randomStruct; /* random structure */
{
NN_DIGIT d[MAX_NN_DIGITS], dP[MAX_NN_DIGITS], dQ[MAX_NN_DIGITS],
e[MAX_NN_DIGITS], n[MAX_NN_DIGITS], p[MAX_NN_DIGITS], phiN[MAX_NN_DIGITS],
pMinus1[MAX_NN_DIGITS], q[MAX_NN_DIGITS], qInv[MAX_NN_DIGITS],
qMinus1[MAX_NN_DIGITS], t[MAX_NN_DIGITS], u[MAX_NN_DIGITS],
v[MAX_NN_DIGITS];
int status = 0;
unsigned int nDigits, pBits, pDigits, qBits;
if ((protoKey->bits < MIN_RSA_MODULUS_BITS) ||
(protoKey->bits > MAX_RSA_MODULUS_BITS))
return (RE_MODULUS_LEN);
nDigits = (protoKey->bits + NN_DIGIT_BITS - 1) / NN_DIGIT_BITS;
pDigits = (nDigits + 1) / 2;
pBits = (protoKey->bits + 1) / 2;
qBits = protoKey->bits - pBits;
/* NOTE: for 65537, this assumes NN_DIGIT is at least 17 bits. */
NN_ASSIGN_DIGIT
(e, protoKey->useFermat4 ? (NN_DIGIT)65537 : (NN_DIGIT)3, nDigits);
/* Generate prime p between 3*2^(pBits-2) and 2^pBits-1, searching
in steps of 2, until one satisfies gcd (p-1, e) = 1.
*/
NN_Assign2Exp (t, pBits-1, pDigits);
NN_Assign2Exp (u, pBits-2, pDigits);
NN_Add (t, t, u, pDigits);
NN_ASSIGN_DIGIT (v, 1, pDigits);
NN_Sub (v, t, v, pDigits);
NN_Add (u, u, v, pDigits);
NN_ASSIGN_DIGIT (v, 2, pDigits);
do {
if ((status = GeneratePrime (p, t, u, v, pDigits, randomStruct)))
return (status);
}
while (! RSAFilter (p, pDigits, e, 1));
/* Generate prime q between 3*2^(qBits-2) and 2^qBits-1, searching
in steps of 2, until one satisfies gcd (q-1, e) = 1.
*/
NN_Assign2Exp (t, qBits-1, pDigits);
NN_Assign2Exp (u, qBits-2, pDigits);
NN_Add (t, t, u, pDigits);
NN_ASSIGN_DIGIT (v, 1, pDigits);
NN_Sub (v, t, v, pDigits);
NN_Add (u, u, v, pDigits);
NN_ASSIGN_DIGIT (v, 2, pDigits);
do {
if ((status = GeneratePrime (q, t, u, v, pDigits, randomStruct)))
return (status);
}
while (! RSAFilter (q, pDigits, e, 1));
/* Sort so that p > q. (p = q case is extremely unlikely.)
*/
if (NN_Cmp (p, q, pDigits) < 0) {
NN_Assign (t, p, pDigits);
NN_Assign (p, q, pDigits);
NN_Assign (q, t, pDigits);
}
/* Compute n = pq, qInv = q^{-1} mod p, d = e^{-1} mod (p-1)(q-1),
dP = d mod p-1, dQ = d mod q-1.
*/
NN_Mult (n, p, q, pDigits);
NN_ModInv (qInv, q, p, pDigits);
NN_ASSIGN_DIGIT (t, 1, pDigits);
NN_Sub (pMinus1, p, t, pDigits);
NN_Sub (qMinus1, q, t, pDigits);
NN_Mult (phiN, pMinus1, qMinus1, pDigits);
NN_ModInv (d, e, phiN, nDigits);
NN_Mod (dP, d, nDigits, pMinus1, pDigits);
NN_Mod (dQ, d, nDigits, qMinus1, pDigits);
publicKey->bits = privateKey->bits = protoKey->bits;
NN_Encode (publicKey->modulus, MAX_RSA_MODULUS_LEN, n, nDigits);
NN_Encode (publicKey->exponent, MAX_RSA_MODULUS_LEN, e, 1);
R_memcpy
((POINTER)privateKey->modulus, (POINTER)publicKey->modulus,
MAX_RSA_MODULUS_LEN);
R_memcpy
((POINTER)privateKey->publicExponent, (POINTER)publicKey->exponent,
MAX_RSA_MODULUS_LEN);
NN_Encode (privateKey->exponent, MAX_RSA_MODULUS_LEN, d, nDigits);
NN_Encode (privateKey->prime[0], MAX_RSA_PRIME_LEN, p, pDigits);
NN_Encode (privateKey->prime[1], MAX_RSA_PRIME_LEN, q, pDigits);
NN_Encode (privateKey->primeExponent[0], MAX_RSA_PRIME_LEN, dP, pDigits);
NN_Encode (privateKey->primeExponent[1], MAX_RSA_PRIME_LEN, dQ, pDigits);
NN_Encode (privateKey->coefficient, MAX_RSA_PRIME_LEN, qInv, pDigits);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)d, 0, sizeof (d));
R_memset ((POINTER)dP, 0, sizeof (dP));
R_memset ((POINTER)dQ, 0, sizeof (dQ));
R_memset ((POINTER)p, 0, sizeof (p));
R_memset ((POINTER)phiN, 0, sizeof (phiN));
R_memset ((POINTER)pMinus1, 0, sizeof (pMinus1));
R_memset ((POINTER)q, 0, sizeof (q));
R_memset ((POINTER)qInv, 0, sizeof (qInv));
R_memset ((POINTER)qMinus1, 0, sizeof (qMinus1));
R_memset ((POINTER)t, 0, sizeof (t));
return (0);
}
/* Returns nonzero iff GCD (a-1, b) = 1.
Lengths: a[aDigits], b[bDigits].
Assumes aDigits < MAX_NN_DIGITS, bDigits < MAX_NN_DIGITS.
*/
static int RSAFilter (a, aDigits, b, bDigits)
NN_DIGIT *a, *b;
unsigned int aDigits, bDigits;
{
int status;
NN_DIGIT aMinus1[MAX_NN_DIGITS], t[MAX_NN_DIGITS];
NN_ASSIGN_DIGIT (t, 1, aDigits);
NN_Sub (aMinus1, a, t, aDigits);
status = RelativelyPrime (aMinus1, aDigits, b, bDigits);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)aMinus1, 0, sizeof (aMinus1));
return (status);
}
/* Returns nonzero iff a and b are relatively prime.
Lengths: a[aDigits], b[bDigits].
Assumes aDigits >= bDigits, aDigits < MAX_NN_DIGITS.
*/
static int RelativelyPrime (a, aDigits, b, bDigits)
NN_DIGIT *a, *b;
unsigned int aDigits, bDigits;
{
int status;
NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS];
NN_AssignZero (t, aDigits);
NN_Assign (t, b, bDigits);
NN_Gcd (t, a, t, aDigits);
NN_ASSIGN_DIGIT (u, 1, aDigits);
status = NN_EQUAL (t, u, aDigits);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)t, 0, sizeof (t));
return (status);
}

111
lib/rsaref/r_random.c Normal file
View file

@ -0,0 +1,111 @@
/* R_RANDOM.C - random objects for RSAREF
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
#include "global.h"
#include "rsaref.h"
#include "r_random.h"
#include "md5.h"
#define RANDOM_BYTES_NEEDED 256
int R_RandomInit (randomStruct)
R_RANDOM_STRUCT *randomStruct; /* new random structure */
{
randomStruct->bytesNeeded = RANDOM_BYTES_NEEDED;
R_memset ((POINTER)randomStruct->state, 0, sizeof (randomStruct->state));
randomStruct->outputAvailable = 0;
return (0);
}
int R_RandomUpdate (randomStruct, block, blockLen)
R_RANDOM_STRUCT *randomStruct; /* random structure */
unsigned char *block; /* block of values to mix in */
unsigned int blockLen; /* length of block */
{
MD5_CTX context;
unsigned char digest[16];
unsigned int i, x;
MD5Init (&context);
MD5Update (&context, block, blockLen);
MD5Final (digest, &context);
/* add digest to state */
x = 0;
for (i = 0; i < 16; i++) {
x += randomStruct->state[15-i] + digest[15-i];
randomStruct->state[15-i] = (unsigned char)x;
x >>= 8;
}
if (randomStruct->bytesNeeded < blockLen)
randomStruct->bytesNeeded = 0;
else
randomStruct->bytesNeeded -= blockLen;
/* Zeroize sensitive information.
*/
R_memset ((POINTER)digest, 0, sizeof (digest));
x = 0;
return (0);
}
int R_GetRandomBytesNeeded (bytesNeeded, randomStruct)
unsigned int *bytesNeeded; /* number of mix-in bytes needed */
R_RANDOM_STRUCT *randomStruct; /* random structure */
{
*bytesNeeded = randomStruct->bytesNeeded;
return (0);
}
int R_GenerateBytes (block, blockLen, randomStruct)
unsigned char *block; /* block */
unsigned int blockLen; /* length of block */
R_RANDOM_STRUCT *randomStruct; /* random structure */
{
MD5_CTX context;
unsigned int available, i;
if (randomStruct->bytesNeeded)
return (RE_NEED_RANDOM);
available = randomStruct->outputAvailable;
while (blockLen > available) {
R_memcpy
((POINTER)block, (POINTER)&randomStruct->output[16-available],
available);
block += available;
blockLen -= available;
/* generate new output */
MD5Init (&context);
MD5Update (&context, randomStruct->state, 16);
MD5Final (randomStruct->output, &context);
available = 16;
/* increment state */
for (i = 0; i < 16; i++)
if (randomStruct->state[15-i]++)
break;
}
R_memcpy
((POINTER)block, (POINTER)&randomStruct->output[16-available], blockLen);
randomStruct->outputAvailable = available - blockLen;
return (0);
}
void R_RandomFinal (randomStruct)
R_RANDOM_STRUCT *randomStruct; /* random structure */
{
R_memset ((POINTER)randomStruct, 0, sizeof (*randomStruct));
}

9
lib/rsaref/r_random.h Normal file
View file

@ -0,0 +1,9 @@
/* R_RANDOM.H - header file for R_RANDOM.C
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
int R_GenerateBytes PROTO_LIST
((unsigned char *, unsigned int, R_RANDOM_STRUCT *));

39
lib/rsaref/r_stdlib.c Normal file
View file

@ -0,0 +1,39 @@
/* R_STDLIB.C - platform-specific C library routines for RSAREF
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
#include <string.h>
#include "global.h"
#include "rsaref.h"
void R_memset (output, value, len)
POINTER output; /* output block */
int value; /* value */
unsigned int len; /* length of block */
{
if (len)
memset (output, value, len);
}
void R_memcpy (output, input, len)
POINTER output; /* output block */
POINTER input; /* input block */
unsigned int len; /* length of blocks */
{
if (len)
memcpy (output, input, len);
}
int R_memcmp (firstBlock, secondBlock, len)
POINTER firstBlock; /* first block */
POINTER secondBlock; /* second block */
unsigned int len; /* length of blocks */
{
if (len)
return (memcmp (firstBlock, secondBlock, len));
else
return (0);
}

324
lib/rsaref/rsa.c Normal file
View file

@ -0,0 +1,324 @@
/* RSA.C - RSA routines for RSAREF
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
#include "global.h"
#include "rsaref.h"
#include "r_random.h"
#include "rsa.h"
#include "nn.h"
static int RSAPublicBlock PROTO_LIST
((unsigned char *, unsigned int *, unsigned char *, unsigned int,
R_RSA_PUBLIC_KEY *));
static int RSAPrivateBlock PROTO_LIST
((unsigned char *, unsigned int *, unsigned char *, unsigned int,
R_RSA_PRIVATE_KEY *));
/* RSA public-key encryption, according to PKCS #1.
*/
int RSAPublicEncrypt
(output, outputLen, input, inputLen, publicKey, randomStruct)
unsigned char *output; /* output block */
unsigned int *outputLen; /* length of output block */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */
R_RANDOM_STRUCT *randomStruct; /* random structure */
{
int status;
unsigned char byte, pkcsBlock[MAX_RSA_MODULUS_LEN];
unsigned int i, modulusLen;
modulusLen = (publicKey->bits + 7) / 8;
if (inputLen + 11 > modulusLen)
return (RE_LEN);
pkcsBlock[0] = 0;
/* block type 2 */
pkcsBlock[1] = 2;
for (i = 2; i < modulusLen - inputLen - 1; i++) {
/* Find nonzero random byte.
*/
do {
R_GenerateBytes (&byte, 1, randomStruct);
} while (byte == 0);
pkcsBlock[i] = byte;
}
/* separator */
pkcsBlock[i++] = 0;
R_memcpy ((POINTER)&pkcsBlock[i], (POINTER)input, inputLen);
status = RSAPublicBlock
(output, outputLen, pkcsBlock, modulusLen, publicKey);
/* Zeroize sensitive information.
*/
byte = 0;
R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
return (status);
}
/* RSA public-key decryption, according to PKCS #1.
*/
int RSAPublicDecrypt (output, outputLen, input, inputLen, publicKey)
unsigned char *output; /* output block */
unsigned int *outputLen; /* length of output block */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */
{
int status;
unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
unsigned int i, modulusLen, pkcsBlockLen;
modulusLen = (publicKey->bits + 7) / 8;
if (inputLen > modulusLen)
return (RE_LEN);
if ((status = RSAPublicBlock
(pkcsBlock, &pkcsBlockLen, input, inputLen, publicKey)))
return (status);
if (pkcsBlockLen != modulusLen)
return (RE_LEN);
/* Require block type 1.
*/
if ((pkcsBlock[0] != 0) || (pkcsBlock[1] != 1))
return (RE_DATA);
for (i = 2; i < modulusLen-1; i++)
if (pkcsBlock[i] != 0xff)
break;
/* separator */
if (pkcsBlock[i++] != 0)
return (RE_DATA);
*outputLen = modulusLen - i;
if (*outputLen + 11 > modulusLen)
return (RE_DATA);
R_memcpy ((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen);
/* Zeroize potentially sensitive information.
*/
R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
return (0);
}
/* RSA private-key encryption, according to PKCS #1.
*/
int RSAPrivateEncrypt (output, outputLen, input, inputLen, privateKey)
unsigned char *output; /* output block */
unsigned int *outputLen; /* length of output block */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */
{
int status;
unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
unsigned int i, modulusLen;
modulusLen = (privateKey->bits + 7) / 8;
if (inputLen + 11 > modulusLen)
return (RE_LEN);
pkcsBlock[0] = 0;
/* block type 1 */
pkcsBlock[1] = 1;
for (i = 2; i < modulusLen - inputLen - 1; i++)
pkcsBlock[i] = 0xff;
/* separator */
pkcsBlock[i++] = 0;
R_memcpy ((POINTER)&pkcsBlock[i], (POINTER)input, inputLen);
status = RSAPrivateBlock
(output, outputLen, pkcsBlock, modulusLen, privateKey);
/* Zeroize potentially sensitive information.
*/
R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
return (status);
}
/* RSA private-key decryption, according to PKCS #1.
*/
int RSAPrivateDecrypt (output, outputLen, input, inputLen, privateKey)
unsigned char *output; /* output block */
unsigned int *outputLen; /* length of output block */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */
{
int status;
unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
unsigned int i, modulusLen, pkcsBlockLen;
modulusLen = (privateKey->bits + 7) / 8;
if (inputLen > modulusLen)
return (RE_LEN);
if ((status = RSAPrivateBlock
(pkcsBlock, &pkcsBlockLen, input, inputLen, privateKey)))
return (status);
if (pkcsBlockLen != modulusLen)
return (RE_LEN);
/* Require block type 2.
*/
if ((pkcsBlock[0] != 0) || (pkcsBlock[1] != 2))
return (RE_DATA);
for (i = 2; i < modulusLen-1; i++)
/* separator */
if (pkcsBlock[i] == 0)
break;
i++;
if (i >= modulusLen)
return (RE_DATA);
*outputLen = modulusLen - i;
if (*outputLen + 11 > modulusLen)
return (RE_DATA);
R_memcpy ((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
return (0);
}
/* Raw RSA public-key operation. Output has same length as modulus.
Assumes inputLen < length of modulus.
Requires input < modulus.
*/
static int RSAPublicBlock (output, outputLen, input, inputLen, publicKey)
unsigned char *output; /* output block */
unsigned int *outputLen; /* length of output block */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */
{
NN_DIGIT c[MAX_NN_DIGITS], e[MAX_NN_DIGITS], m[MAX_NN_DIGITS],
n[MAX_NN_DIGITS];
unsigned int eDigits, nDigits;
NN_Decode (m, MAX_NN_DIGITS, input, inputLen);
NN_Decode (n, MAX_NN_DIGITS, publicKey->modulus, MAX_RSA_MODULUS_LEN);
NN_Decode (e, MAX_NN_DIGITS, publicKey->exponent, MAX_RSA_MODULUS_LEN);
nDigits = NN_Digits (n, MAX_NN_DIGITS);
eDigits = NN_Digits (e, MAX_NN_DIGITS);
if (NN_Cmp (m, n, nDigits) >= 0)
return (RE_DATA);
/* Compute c = m^e mod n.
*/
NN_ModExp (c, m, e, eDigits, n, nDigits);
*outputLen = (publicKey->bits + 7) / 8;
NN_Encode (output, *outputLen, c, nDigits);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)c, 0, sizeof (c));
R_memset ((POINTER)m, 0, sizeof (m));
return (0);
}
/* Raw RSA private-key operation. Output has same length as modulus.
Assumes inputLen < length of modulus.
Requires input < modulus.
*/
static int RSAPrivateBlock (output, outputLen, input, inputLen, privateKey)
unsigned char *output; /* output block */
unsigned int *outputLen; /* length of output block */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */
{
NN_DIGIT c[MAX_NN_DIGITS], cP[MAX_NN_DIGITS], cQ[MAX_NN_DIGITS],
dP[MAX_NN_DIGITS], dQ[MAX_NN_DIGITS], mP[MAX_NN_DIGITS],
mQ[MAX_NN_DIGITS], n[MAX_NN_DIGITS], p[MAX_NN_DIGITS], q[MAX_NN_DIGITS],
qInv[MAX_NN_DIGITS], t[MAX_NN_DIGITS];
unsigned int cDigits, nDigits, pDigits;
NN_Decode (c, MAX_NN_DIGITS, input, inputLen);
NN_Decode (n, MAX_NN_DIGITS, privateKey->modulus, MAX_RSA_MODULUS_LEN);
NN_Decode (p, MAX_NN_DIGITS, privateKey->prime[0], MAX_RSA_PRIME_LEN);
NN_Decode (q, MAX_NN_DIGITS, privateKey->prime[1], MAX_RSA_PRIME_LEN);
NN_Decode
(dP, MAX_NN_DIGITS, privateKey->primeExponent[0], MAX_RSA_PRIME_LEN);
NN_Decode
(dQ, MAX_NN_DIGITS, privateKey->primeExponent[1], MAX_RSA_PRIME_LEN);
NN_Decode (qInv, MAX_NN_DIGITS, privateKey->coefficient, MAX_RSA_PRIME_LEN);
cDigits = NN_Digits (c, MAX_NN_DIGITS);
nDigits = NN_Digits (n, MAX_NN_DIGITS);
pDigits = NN_Digits (p, MAX_NN_DIGITS);
if (NN_Cmp (c, n, nDigits) >= 0)
return (RE_DATA);
/* Compute mP = cP^dP mod p and mQ = cQ^dQ mod q. (Assumes q has
length at most pDigits, i.e., p > q.)
*/
NN_Mod (cP, c, cDigits, p, pDigits);
NN_Mod (cQ, c, cDigits, q, pDigits);
NN_ModExp (mP, cP, dP, pDigits, p, pDigits);
NN_AssignZero (mQ, nDigits);
NN_ModExp (mQ, cQ, dQ, pDigits, q, pDigits);
/* Chinese Remainder Theorem:
m = ((((mP - mQ) mod p) * qInv) mod p) * q + mQ.
*/
if (NN_Cmp (mP, mQ, pDigits) >= 0)
NN_Sub (t, mP, mQ, pDigits);
else {
NN_Sub (t, mQ, mP, pDigits);
NN_Sub (t, p, t, pDigits);
}
NN_ModMult (t, t, qInv, p, pDigits);
NN_Mult (t, t, q, pDigits);
NN_Add (t, t, mQ, nDigits);
*outputLen = (privateKey->bits + 7) / 8;
NN_Encode (output, *outputLen, t, nDigits);
/* Zeroize sensitive information.
*/
R_memset ((POINTER)c, 0, sizeof (c));
R_memset ((POINTER)cP, 0, sizeof (cP));
R_memset ((POINTER)cQ, 0, sizeof (cQ));
R_memset ((POINTER)dP, 0, sizeof (dP));
R_memset ((POINTER)dQ, 0, sizeof (dQ));
R_memset ((POINTER)mP, 0, sizeof (mP));
R_memset ((POINTER)mQ, 0, sizeof (mQ));
R_memset ((POINTER)p, 0, sizeof (p));
R_memset ((POINTER)q, 0, sizeof (q));
R_memset ((POINTER)qInv, 0, sizeof (qInv));
R_memset ((POINTER)t, 0, sizeof (t));
return (0);
}

19
lib/rsaref/rsa.h Normal file
View file

@ -0,0 +1,19 @@
/* RSA.H - header file for RSA.C
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
int RSAPublicEncrypt PROTO_LIST
((unsigned char *, unsigned int *, unsigned char *, unsigned int,
R_RSA_PUBLIC_KEY *, R_RANDOM_STRUCT *));
int RSAPrivateEncrypt PROTO_LIST
((unsigned char *, unsigned int *, unsigned char *, unsigned int,
R_RSA_PRIVATE_KEY *));
int RSAPublicDecrypt PROTO_LIST
((unsigned char *, unsigned int *, unsigned char *, unsigned int,
R_RSA_PUBLIC_KEY *));
int RSAPrivateDecrypt PROTO_LIST
((unsigned char *, unsigned int *, unsigned char *, unsigned int,
R_RSA_PRIVATE_KEY *));

253
lib/rsaref/rsaref.h Normal file
View file

@ -0,0 +1,253 @@
/* RSAREF.H - header file for RSAREF cryptographic toolkit
*/
/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
Inc., created 1991. All rights reserved.
*/
#ifndef _RSAREF_H_
#define _RSAREF_H_ 1
#include "global.h"
#include "md2.h"
#include "md5.h"
#include "des.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Message-digest algorithms.
*/
#define DA_MD2 3
#define DA_MD5 5
/* Encryption algorithms to be ored with digest algorithm in Seal and Open.
*/
#define EA_DES_CBC 1
#define EA_DES_EDE2_CBC 2
#define EA_DES_EDE3_CBC 3
#define EA_DESX_CBC 4
/* RSA key lengths.
*/
#define MIN_RSA_MODULUS_BITS 508
#define MAX_RSA_MODULUS_BITS 1024
#define MAX_RSA_MODULUS_LEN ((MAX_RSA_MODULUS_BITS + 7) / 8)
#define MAX_RSA_PRIME_BITS ((MAX_RSA_MODULUS_BITS + 1) / 2)
#define MAX_RSA_PRIME_LEN ((MAX_RSA_PRIME_BITS + 7) / 8)
/* Maximum lengths of encoded and encrypted content, as a function of
content length len. Also, inverse functions.
*/
#define ENCODED_CONTENT_LEN(len) (4*(len)/3 + 3)
#define ENCRYPTED_CONTENT_LEN(len) ENCODED_CONTENT_LEN ((len)+8)
#define DECODED_CONTENT_LEN(len) (3*(len)/4 + 1)
#define DECRYPTED_CONTENT_LEN(len) (DECODED_CONTENT_LEN (len) - 1)
/* Maximum lengths of signatures, encrypted keys, encrypted
signatures, and message digests.
*/
#define MAX_SIGNATURE_LEN MAX_RSA_MODULUS_LEN
#define MAX_PEM_SIGNATURE_LEN ENCODED_CONTENT_LEN (MAX_SIGNATURE_LEN)
#define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN
#define MAX_PEM_ENCRYPTED_KEY_LEN ENCODED_CONTENT_LEN (MAX_ENCRYPTED_KEY_LEN)
#define MAX_PEM_ENCRYPTED_SIGNATURE_LEN \
ENCRYPTED_CONTENT_LEN (MAX_SIGNATURE_LEN)
#define MAX_DIGEST_LEN 16
/* Maximum length of Diffie-Hellman parameters.
*/
#define DH_PRIME_LEN(bits) (((bits) + 7) / 8)
/* Error codes.
*/
#define RE_CONTENT_ENCODING 0x0400
#define RE_DATA 0x0401
#define RE_DIGEST_ALGORITHM 0x0402
#define RE_ENCODING 0x0403
#define RE_KEY 0x0404
#define RE_KEY_ENCODING 0x0405
#define RE_LEN 0x0406
#define RE_MODULUS_LEN 0x0407
#define RE_NEED_RANDOM 0x0408
#define RE_PRIVATE_KEY 0x0409
#define RE_PUBLIC_KEY 0x040a
#define RE_SIGNATURE 0x040b
#define RE_SIGNATURE_ENCODING 0x040c
#define RE_ENCRYPTION_ALGORITHM 0x040d
/* Random structure.
*/
typedef struct {
unsigned int bytesNeeded;
unsigned char state[16];
unsigned int outputAvailable;
unsigned char output[16];
} R_RANDOM_STRUCT;
/* RSA public and private key.
*/
typedef struct {
unsigned int bits; /* length in bits of modulus */
unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */
unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* public exponent */
} R_RSA_PUBLIC_KEY;
typedef struct {
unsigned int bits; /* length in bits of modulus */
unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */
unsigned char publicExponent[MAX_RSA_MODULUS_LEN]; /* public exponent */
unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* private exponent */
unsigned char prime[2][MAX_RSA_PRIME_LEN]; /* prime factors */
unsigned char primeExponent[2][MAX_RSA_PRIME_LEN]; /* exponents for CRT */
unsigned char coefficient[MAX_RSA_PRIME_LEN]; /* CRT coefficient */
} R_RSA_PRIVATE_KEY;
/* RSA prototype key.
*/
typedef struct {
unsigned int bits; /* length in bits of modulus */
int useFermat4; /* public exponent (1 = F4, 0 = 3) */
} R_RSA_PROTO_KEY;
/* Diffie-Hellman parameters.
*/
typedef struct {
unsigned char *prime; /* prime */
unsigned int primeLen; /* length of prime */
unsigned char *generator; /* generator */
unsigned int generatorLen; /* length of generator */
} R_DH_PARAMS;
typedef struct {
int digestAlgorithm;
union {
MD2_CTX md2;
MD5_CTX md5;
} context;
} R_DIGEST_CTX;
typedef struct {
R_DIGEST_CTX digestContext;
} R_SIGNATURE_CTX;
typedef struct {
int encryptionAlgorithm;
union {
DES_CBC_CTX des;
DES3_CBC_CTX des3;
DESX_CBC_CTX desx;
} cipherContext;
unsigned char buffer[8];
unsigned int bufferLen;
} R_ENVELOPE_CTX;
/* Random structures.
*/
int R_RandomInit PROTO_LIST ((R_RANDOM_STRUCT *));
int R_RandomUpdate PROTO_LIST
((R_RANDOM_STRUCT *, unsigned char *, unsigned int));
int R_GetRandomBytesNeeded PROTO_LIST ((unsigned int *, R_RANDOM_STRUCT *));
void R_RandomFinal PROTO_LIST ((R_RANDOM_STRUCT *));
/* Cryptographic procedures "by parts"
*/
int R_DigestInit PROTO_LIST ((R_DIGEST_CTX *, int));
int R_DigestUpdate PROTO_LIST
((R_DIGEST_CTX *, unsigned char *, unsigned int));
int R_DigestFinal PROTO_LIST
((R_DIGEST_CTX *, unsigned char *, unsigned int *));
int R_SignInit PROTO_LIST ((R_SIGNATURE_CTX *, int));
int R_SignUpdate PROTO_LIST
((R_SIGNATURE_CTX *, unsigned char *, unsigned int));
int R_SignFinal PROTO_LIST
((R_SIGNATURE_CTX *, unsigned char *, unsigned int *, R_RSA_PRIVATE_KEY *));
int R_VerifyInit PROTO_LIST ((R_SIGNATURE_CTX *, int));
int R_VerifyUpdate PROTO_LIST
((R_SIGNATURE_CTX *, unsigned char *, unsigned int));
int R_VerifyFinal PROTO_LIST
((R_SIGNATURE_CTX *, unsigned char *, unsigned int, R_RSA_PUBLIC_KEY *));
int R_SealInit PROTO_LIST
((R_ENVELOPE_CTX *, unsigned char **, unsigned int *, unsigned char [8],
unsigned int, R_RSA_PUBLIC_KEY **, int, R_RANDOM_STRUCT *));
int R_SealUpdate PROTO_LIST
((R_ENVELOPE_CTX *, unsigned char *, unsigned int *, unsigned char *,
unsigned int));
int R_SealFinal PROTO_LIST
((R_ENVELOPE_CTX *, unsigned char *, unsigned int *));
int R_OpenInit PROTO_LIST
((R_ENVELOPE_CTX *, int, unsigned char *, unsigned int, unsigned char [8],
R_RSA_PRIVATE_KEY *));
int R_OpenUpdate PROTO_LIST
((R_ENVELOPE_CTX *, unsigned char *, unsigned int *, unsigned char *,
unsigned int));
int R_OpenFinal PROTO_LIST
((R_ENVELOPE_CTX *, unsigned char *, unsigned int *));
/* Cryptographic enhancements by block.
*/
int R_SignPEMBlock PROTO_LIST
((unsigned char *, unsigned int *, unsigned char *, unsigned int *,
unsigned char *, unsigned int, int, int, R_RSA_PRIVATE_KEY *));
int R_SignBlock PROTO_LIST
((unsigned char *, unsigned int *, unsigned char *, unsigned int, int,
R_RSA_PRIVATE_KEY *));
int R_VerifyPEMSignature PROTO_LIST
((unsigned char *, unsigned int *, unsigned char *, unsigned int,
unsigned char *, unsigned int, int, int, R_RSA_PUBLIC_KEY *));
int R_VerifyBlockSignature PROTO_LIST
((unsigned char *, unsigned int, unsigned char *, unsigned int, int,
R_RSA_PUBLIC_KEY *));
int R_SealPEMBlock PROTO_LIST
((unsigned char *, unsigned int *, unsigned char *, unsigned int *,
unsigned char *, unsigned int *, unsigned char [8], unsigned char *,
unsigned int, int, R_RSA_PUBLIC_KEY *, R_RSA_PRIVATE_KEY *,
R_RANDOM_STRUCT *));
int R_OpenPEMBlock PROTO_LIST
((unsigned char *, unsigned int *, unsigned char *, unsigned int,
unsigned char *, unsigned int, unsigned char *, unsigned int,
unsigned char [8], int, R_RSA_PRIVATE_KEY *, R_RSA_PUBLIC_KEY *));
int R_DigestBlock PROTO_LIST
((unsigned char *, unsigned int *, unsigned char *, unsigned int, int));
/* Printable ASCII encoding and decoding.
*/
int R_EncodePEMBlock PROTO_LIST
((unsigned char *, unsigned int *, unsigned char *, unsigned int));
int R_DecodePEMBlock PROTO_LIST
((unsigned char *, unsigned int *, unsigned char *, unsigned int));
/* Key-pair generation.
*/
int R_GeneratePEMKeys PROTO_LIST
((R_RSA_PUBLIC_KEY *, R_RSA_PRIVATE_KEY *, R_RSA_PROTO_KEY *,
R_RANDOM_STRUCT *));
/* Diffie-Hellman key agreement.
*/
int R_GenerateDHParams PROTO_LIST
((R_DH_PARAMS *, unsigned int, unsigned int, R_RANDOM_STRUCT *));
int R_SetupDHAgreement PROTO_LIST
((unsigned char *, unsigned char *, unsigned int, R_DH_PARAMS *,
R_RANDOM_STRUCT *));
int R_ComputeDHAgreedKey PROTO_LIST
((unsigned char *, unsigned char *, unsigned char *, unsigned int,
R_DH_PARAMS *));
/* Routines supplied by the implementor.
*/
void R_memset PROTO_LIST ((POINTER, int, unsigned int));
void R_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
int R_memcmp PROTO_LIST ((POINTER, POINTER, unsigned int));
#ifdef __cplusplus
}
#endif
#endif

79
t/Makefile.am Normal file
View file

@ -0,0 +1,79 @@
# $Id$
AM_CPPFLAGS = -I$(top_srcdir)/include
if WITH_BENCHMARKS
AM_CPPFLAGS += -DBENCHMARKS
endif
noinst_HEADERS = t.h
# Common support code
check_LTLIBRARIES = libt.la
libt_la_SOURCES = t_main.c t_file.c
# Link in the test driver and the full cryb library
LDADD = $(builddir)/libt.la \
$(top_builddir)/lib/core/libcryb-core.la \
$(top_builddir)/lib/enc/libcryb-enc.la \
$(top_builddir)/lib/digest/libcryb-digest.la \
$(top_builddir)/lib/mac/libcryb-mac.la \
$(top_builddir)/lib/rand/libcryb-rand.la \
$(top_builddir)/lib/oath/libcryb-oath.la
# Additional headers, flags and libraries for OpenSSL
if WITH_OPENSSL
OPENSSL_INCLUDES = $(INCLUDES)
OPENSSL_CFLAGS = -DWITH_OPENSSL=1
OPENSSL_LDADD = $(LDADD) -lcrypto
endif
# Additional headers, flags and libraries for RSAREF
if WITH_RSAREF
RSAREF_INCLUDES = $(INCLUDES) -I$(top_srcdir)/lib/rsaref
RSAREF_CFLAGS = -DWITH_RSAREF=1 -DPROTOTYPES=1
RSAREF_LDADD = $(LDADD) $(top_builddir)/lib/rsaref/librsaref.la
endif
# tests
TESTS =
# libcryb-core
TESTS += t_ctype
# libcryb-enc
TESTS += t_rfc3986 t_rfc4648
# libcryb-digest
TESTS += t_md5
if WITH_OPENSSL
TESTS += t_md5_openssl
t_md5_openssl_SOURCES = t_md5.c
t_md5_openssl_CFLAGS = $(OPENSSL_INCLUDES) $(OPENSSL_CFLAGS)
t_md5_openssl_LDADD = $(OPENSSL_LDADD)
endif
if WITH_RSAREF
TESTS += t_md5_rsaref
t_md5_rsaref_SOURCES = t_md5.c
t_md5_rsaref_CFLAGS = $(RSAREF_INCLUDES) $(RSAREF_CFLAGS)
t_md5_rsaref_LDADD = $(RSAREF_LDADD)
endif
TESTS += t_sha1
if WITH_OPENSSL
TESTS += t_sha1_openssl
t_sha1_openssl_SOURCES = t_sha1.c
t_sha1_openssl_CFLAGS = $(OPENSSL_INCLUDES) $(OPENSSL_CFLAGS)
t_sha1_openssl_LDADD = $(OPENSSL_LDADD)
endif
# libcryb-mac
TESTS += t_hmac
if WITH_OPENSSL
TESTS += t_hmac_openssl
t_hmac_openssl_SOURCES = t_hmac.c
t_hmac_openssl_CFLAGS = $(OPENSSL_INCLUDES) $(OPENSSL_CFLAGS)
t_hmac_openssl_LDADD = $(OPENSSL_LDADD)
endif
check_PROGRAMS = $(TESTS)

82
t/t.h Normal file
View file

@ -0,0 +1,82 @@
/*-
* Copyright (c) 2012-2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#ifndef T_H_INCLUDED
#define T_H_INCLUDED
CRYB_DISABLE_COVERAGE
/*
* Structure describing a test. Includes a pointer to the function that
* performs the test, a pointer to the default description or comment
* associated with the test, and a pointer to arbitrary data passed to the
* test function.
*/
typedef int (t_func)(char **, void *);
struct t_test {
t_func *func;
void *arg;
char *desc;
};
extern const char *t_progname;
void t_add_test(t_func *, void *, const char *, ...);
void t_add_tests(struct t_test *, int);
int t_prepare(int, char **);
void t_cleanup(void);
void t_verbose_hex(const uint8_t *, size_t);
void t_verbose(const char *, ...)
CRYB_PRINTF(1, 2);
/*
* Convenience functions for temp files
*/
struct t_file {
char *name;
FILE *file;
struct t_file *prev, *next;
};
struct t_file *t_fopen(const char *);
int t_fprintf(struct t_file *, const char *, ...)
CRYB_PRINTF(2, 3);
int t_ferror(struct t_file *);
int t_feof(struct t_file *);
void t_frewind(struct t_file *);
void t_fclose(struct t_file *);
void t_fcloseall(void);
#endif

123
t/t_ctype.c Normal file
View file

@ -0,0 +1,123 @@
/*-
* Copyright (c) 2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#include "cryb/impl.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <cryb/ctype.h>
#include "t.h"
#define OC_DIGIT "0123456789"
#define OC_XDIGIT OC_DIGIT "ABCDEFabcdef"
#define OC_UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define OC_LOWER "abcdefghijklmnopqrstuvwxyz"
#define OC_LETTER OC_UPPER OC_LOWER
#define OC_LWS " \t\f\r"
#define OC_WS OC_LWS "\n"
#define OC_P "!\"#$%&'()*+,-./" OC_DIGIT ":;<=>?@" OC_UPPER "[\\]^_`" OC_LOWER "{|}~"
#define OC_PFCS OC_DIGIT OC_LETTER "._-"
static const char oc_digit[] = OC_DIGIT;
static const char oc_xdigit[] = OC_XDIGIT;
static const char oc_upper[] = OC_UPPER;
static const char oc_lower[] = OC_LOWER;
static const char oc_letter[] = OC_LETTER;
static const char oc_lws[] = OC_LWS;
static const char oc_ws[] = OC_WS;
static const char oc_p[] = OC_P;
static const char oc_pfcs[] = OC_PFCS;
#define T_OC(set) \
static int \
t_oc_##set(char **desc, void *arg) \
{ \
char crib[256]; \
unsigned int i, ret; \
\
(void)desc; \
(void)arg; \
memset(crib, 0, sizeof crib); \
for (i = 0; oc_##set[i]; ++i) \
crib[(int)oc_##set[i]] = 1; \
for (i = ret = 0; i < sizeof crib; ++i) { \
if (is_##set(i) != crib[i]) { \
t_verbose("is_%s() incorrect " \
"for %#02x\n", #set, i); \
++ret; \
} \
} \
return (ret == 0); \
}
#define T_OC_ADD(set) t_add_test(&t_oc_##set, NULL, "is_"#set)
T_OC(digit)
T_OC(xdigit)
T_OC(upper)
T_OC(lower)
T_OC(letter)
T_OC(lws)
T_OC(ws)
T_OC(p)
T_OC(pfcs)
/***************************************************************************
* Boilerplate
*/
int
t_prepare(int argc, char *argv[])
{
(void)argc;
(void)argv;
T_OC_ADD(digit);
T_OC_ADD(xdigit);
T_OC_ADD(upper);
T_OC_ADD(lower);
T_OC_ADD(letter);
T_OC_ADD(lws);
T_OC_ADD(ws);
T_OC_ADD(p);
T_OC_ADD(pfcs);
return (0);
}
void
t_cleanup(void)
{
}

158
t/t_file.c Normal file
View file

@ -0,0 +1,158 @@
/*-
* Copyright (c) 2012-2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#include "cryb/impl.h"
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "t.h"
static struct t_file *tflist;
/*
* Open a temp file.
*/
struct t_file *
t_fopen(const char *filename)
{
struct t_file *tf;
int fd;
if ((tf = calloc(sizeof *tf, 1)) == NULL)
err(1, "%s(): calloc()", __func__);
if (filename) {
if ((tf->name = strdup(filename)) == NULL)
err(1, "%s(): strdup()", __func__);
} else {
asprintf(&tf->name, "%s.%lu.%p.tmp",
t_progname, (unsigned long)getpid(), (void *)tf);
if (tf->name == NULL)
err(1, "%s(): asprintf()", __func__);
}
if ((fd = open(tf->name, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0)
err(1, "%s(): %s", __func__, tf->name);
if ((tf->file = fdopen(fd, "r+")) == NULL)
err(1, "%s(): fdopen()", __func__);
if ((tf->next = tflist) != NULL)
tf->next->prev = tf;
tflist = tf;
return (tf);
}
/*
* Write text to the temp file.
*/
int
t_fprintf(struct t_file *tf, const char *fmt, ...)
{
va_list ap;
int len;
va_start(ap, fmt);
len = vfprintf(tf->file, fmt, ap);
va_end(ap);
if (ferror(tf->file))
err(1, "%s(): vfprintf()", __func__);
return (len);
}
/*
* Rewind the temp file.
*/
void
t_frewind(struct t_file *tf)
{
errno = 0;
rewind(tf->file);
if (errno != 0)
err(1, "%s(): rewind()", __func__);
}
/*
* Return non-zero if an error occurred.
*/
int
t_ferror(struct t_file *tf)
{
return (ferror(tf->file));
}
/*
* Return non-zero if the end of the file was reached.
*/
int
t_feof(struct t_file *tf)
{
return (feof(tf->file));
}
/*
* Close a temp file.
*/
void
t_fclose(struct t_file *tf)
{
if (tf == tflist)
tflist = tf->next;
if (tf->prev)
tf->prev->next = tf->next;
if (tf->next)
tf->next->prev = tf->prev;
fclose(tf->file);
if (unlink(tf->name) < 0)
warn("%s(): unlink()", __func__);
free(tf->name);
free(tf);
}
/*
* atexit() function to close all remaining files.
*/
void
t_fcloseall(void)
{
while (tflist)
t_fclose(tflist);
}

225
t/t_hmac.c Normal file
View file

@ -0,0 +1,225 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <err.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "t.h"
#if WITH_OPENSSL
#include <openssl/evp.h>
#include <openssl/hmac.h>
#define HMAC_LEN 20
static void
t_hmac_complete(const void *key, size_t keylen,
const void *msg, size_t msglen, uint8_t *mac)
{
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, key, keylen, EVP_sha1(), NULL);
HMAC_Update(&ctx, msg, msglen);
HMAC_Final(&ctx, mac, NULL);
HMAC_CTX_cleanup(&ctx);
}
#else
#include <cryb/sha1.h>
#include <cryb/hmac.h>
#define t_hmac_complete(key, keylen, msg, msglen, mac) \
hmac_complete(key, keylen, msg, msglen, mac)
#endif
/*
* Test vectors from FIPS 198
*/
static struct t_vector {
const char *desc;
uint8_t key[100];
size_t keylen;
const char *msg;
const uint8_t mac[HMAC_LEN];
} t_hmac_vectors[] = {
{
"zero-length key, zero-length message",
{ },
0,
"",
{
0xfb, 0xdb, 0x1d, 0x1b, 0x18, 0xaa, 0x6c, 0x08,
0x32, 0x4b, 0x7d, 0x64, 0xb7, 0x1f, 0xb7, 0x63,
0x70, 0x69, 0x0e, 0x1d,
},
},
{
"FIPS 198 A.1 (64-byte key)",
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
64,
"Sample #1",
{
0x4f, 0x4c, 0xa3, 0xd5, 0xd6, 0x8b, 0xa7, 0xcc,
0x0a, 0x12, 0x08, 0xc9, 0xc6, 0x1e, 0x9c, 0x5d,
0xa0, 0x40, 0x3c, 0x0a,
},
},
{
"FIPS 198 A.2 (20-byte key)",
{
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43,
},
20,
"Sample #2",
{
0x09, 0x22, 0xd3, 0x40, 0x5f, 0xaa, 0x3d, 0x19,
0x4f, 0x82, 0xa4, 0x58, 0x30, 0x73, 0x7d, 0x5c,
0xc6, 0xc7, 0x5d, 0x24,
},
},
{
"FIPS 198 A.3 (100-byte key)",
{
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3,
},
100,
"Sample #3",
{
0xbc, 0xf4, 0x1e, 0xab, 0x8b, 0xb2, 0xd8, 0x02,
0xf3, 0xd0, 0x5c, 0xaf, 0x7c, 0xb0, 0x92, 0xec,
0xf8, 0xd1, 0xa3, 0xaa,
},
},
{
"FIPS 198 A.4 (49-byte key)",
{
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0,
},
49,
"Sample #4",
{
0x9e, 0xa8, 0x86, 0xef, 0xe2, 0x68, 0xdb, 0xec,
0xce, 0x42, 0x0c, 0x75, 0x24, 0xdf, 0x32, 0xe0,
0x75, 0x1a, 0x2a, 0x26,
},
},
};
/*
* Unit test: compute the HMAC signature of the specified string with the
* specified key and compare it to the expected result.
*/
static int
t_hmac_vector(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t mac[HMAC_LEN];
t_hmac_complete(vector->key, vector->keylen,
(const uint8_t *)vector->msg, strlen(vector->msg),
mac);
if (memcmp(mac, vector->mac, HMAC_LEN) != 0) {
t_verbose("expected ");
t_verbose_hex(vector->mac, HMAC_LEN);
t_verbose("\n");
t_verbose("got ");
t_verbose_hex(mac, HMAC_LEN);
t_verbose("\n");
return (0);
}
return (1);
}
/***************************************************************************
* Boilerplate
*/
int
t_prepare(int argc, char *argv[])
{
int i, n;
(void)argc;
(void)argv;
n = sizeof t_hmac_vectors / sizeof t_hmac_vectors[0];
for (i = 0; i < n; ++i)
t_add_test(t_hmac_vector, &t_hmac_vectors[i],
t_hmac_vectors[i].desc);
return (0);
}
void
t_cleanup(void)
{
}

204
t/t_main.c Normal file
View file

@ -0,0 +1,204 @@
/*-
* Copyright (c) 2012-2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
*
* $Id$
*/
#include "cryb/impl.h"
#include <err.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include "t.h"
/* program name */
const char *t_progname;
/* verbose flag */
static int verbose;
/*
* If verbose flag is set, print an array of bytes in hex
*/
void
t_verbose_hex(const uint8_t *buf, size_t len)
{
if (verbose)
while (len--)
fprintf(stderr, "%02x", *buf++);
}
/*
* If verbose flag is set, print a message
*/
void
t_verbose(const char *fmt, ...)
{
va_list ap;
if (verbose) {
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
}
/*
* Test plan
*/
static struct t_test **t_plan;
static size_t t_plan_len, t_plan_size;
/*
* Grow the test plan to accomodate at least n more entries.
*/
static void
t_grow(int n)
{
struct t_test **p;
if (t_plan_len + n < t_plan_size)
return;
if (t_plan_size == 0)
t_plan_size = 16;
while (t_plan_len + n >= t_plan_size)
t_plan_size *= 2;
if ((p = realloc(t_plan, t_plan_size * sizeof *p)) == NULL)
err(1, "realloc()");
t_plan = p;
}
/*
* Add a single entry to the test plan.
*/
void
t_add_test(t_func *func, void *arg, const char *fmt, ...)
{
struct t_test *t;
va_list ap;
if ((t = malloc(sizeof *t)) == NULL)
err(1, "malloc()");
t->func = func;
va_start(ap, fmt);
vasprintf(&t->desc, fmt, ap);
va_end(ap);
t->arg = arg;
t_grow(1);
t_plan[t_plan_len++] = t;
t_plan[t_plan_len] = NULL;
}
/*
* Add multiple entries to the test plan.
*/
void
t_add_tests(struct t_test *t, int n)
{
int i;
t_grow(n);
for (i = 0; i < n; ++i)
t_plan[t_plan_len++] = &t[i];
t_plan[t_plan_len] = NULL;
}
/*
* Print usage string and exit.
*/
static void
usage(void)
{
fprintf(stderr, "usage: %s [-v]\n", t_progname);
exit(1);
}
int
main(int argc, char *argv[])
{
unsigned int n, pass, fail;
char *desc;
int opt;
/* make stdout line-buffered to preserve ordering */
setvbuf(stdout, NULL, _IOLBF, 0);
/* clean up temp files in case of premature exit */
atexit(t_fcloseall);
/* determine our own name, for naming temp files etc. */
if ((t_progname = strrchr(argv[0], '/')) != NULL)
t_progname++; /* one past the slash */
else
t_progname = argv[0];
/* parse command line options */
while ((opt = getopt(argc, argv, "v")) != -1)
switch (opt) {
case 'v':
verbose = 1;
break;
default:
usage();
}
argc -= optind;
argv += optind;
/* prepare the test plan */
t_prepare(argc, argv);
if (t_plan_len == 0)
errx(1, "no plan\n");
/* run the tests */
printf("1..%zu\n", t_plan_len);
for (n = pass = fail = 0; n < t_plan_len; ++n) {
desc = t_plan[n]->desc ? t_plan[n]->desc : "no description";
if ((*t_plan[n]->func)(&desc, t_plan[n]->arg)) {
printf("ok %d - %s\n", n + 1, desc);
++pass;
} else {
printf("not ok %d - %s\n", n + 1, desc);
++fail;
}
}
/* clean up and exit */
t_cleanup();
exit(fail > 0 ? 1 : 0);
}

289
t/t_md5.c Normal file
View file

@ -0,0 +1,289 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012-2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <err.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "t.h"
#if WITH_OPENSSL
#include <openssl/md5.h>
#define MD5_DIGEST_LEN MD5_DIGEST_LENGTH
static void
t_md5_complete(const void *msg, size_t msglen, uint8_t *digest)
{
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, msg, msglen);
MD5_Final(digest, &ctx);
}
#elif WITH_RSAREF
#include <rsaref.h>
#define MD5_DIGEST_LEN 16
static void
t_md5_complete(const void *msg, size_t msglen, uint8_t *digest)
{
MD5_CTX ctx;
MD5Init(&ctx);
MD5Update(&ctx, (unsigned char *)(uintptr_t)msg, msglen);
MD5Final(digest, &ctx);
}
#else
#include <cryb/md5.h>
#define t_md5_complete(msg, msglen, digest) \
md5_complete(msg, msglen, digest)
#endif
/*
* Test vectors from RFC 1321
*/
static struct t_vector {
const char *msg;
const uint8_t digest[MD5_DIGEST_LEN];
} t_md5_vectors[] = {
{
"",
{
0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e,
}
},
{
"a",
{
0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61,
}
},
{
"abc",
{
0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72,
}
},
{
"message digest",
{
0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0,
}
},
{
"abcdefghijklmnopqrstuvwxyz",
{
0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b,
}
},
{
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789",
{
0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f,
}
},
{
"1234567890123456789012345678901234567890"
"1234567890123456789012345678901234567890",
{
0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a,
}
},
};
/*
* Unit test: compute the MD5 sum of the specified string and compare it
* to the expected result.
*/
static int
t_md5_vector(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t digest[MD5_DIGEST_LEN];
t_md5_complete(vector->msg, strlen(vector->msg), digest);
if (memcmp(digest, vector->digest, MD5_DIGEST_LEN) != 0) {
t_verbose("expected ");
t_verbose_hex(vector->digest, MD5_DIGEST_LEN);
t_verbose("\n");
t_verbose("got ");
t_verbose_hex(digest, MD5_DIGEST_LEN);
t_verbose("\n");
return (0);
}
return (1);
}
#ifdef BENCHMARKS
/*
* Performance test: measure the time spent computing the MD5 sum of a
* message of the specified length.
*/
#define T_PERF_ITERATIONS 1000
static int
t_md5_perf(char **desc CRYB_UNUSED, void *arg)
{
struct timespec ts, te;
unsigned long ns;
uint8_t digest[MD5_DIGEST_LEN];
char *msg, *comment;
if ((msg = calloc(1, msglen)) == NULL)
err(1, "calloc()");
clock_gettime(CLOCK_MONOTONIC_PRECISE, &ts);
for (int i = 0; i < T_PERF_ITERATIONS; ++i)
t_md5_complete(msg, msglen, digest);
clock_gettime(CLOCK_MONOTONIC_PRECISE, &te);
free(msg);
ns = te.tv_sec * 1000000000LU + te.tv_nsec;
ns -= ts.tv_sec * 1000000000LU + ts.tv_nsec;
asprintf(&comment, "%zu bytes: %d iterations in %'lu ns",
msglen, T_PERF_ITERATIONS, ns);
if (comment == NULL)
err(1, "asprintf()");
*desc = (const char *)comment;
return (1);
}
#endif
#if !defined(WITH_OPENSSL) && !defined(WITH_RSAREF)
/*
* Various corner cases and error conditions
*/
static int
t_md5_short_updates(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t digest[MD5_DIGEST_LEN];
md5_ctx ctx;
int i, len;
md5_init(&ctx);
len = strlen(vector->msg);
for (i = 0; i + 5 < len; i += 5)
md5_update(&ctx, vector->msg + i, 5);
md5_update(&ctx, vector->msg + i, len - i);
md5_final(&ctx, digest);
return (memcmp(digest, vector->digest, MD5_DIGEST_LEN) == 0);
}
#endif
#ifdef BENCHMARKS
/*
* Microbenchmarks
*/
int
t_md5_perf_0, "microbenchmark with empty message")
{
return (t_md5_perf(0, desc));
}
T_FUNC(perf_1000, "microbenchmark with 1,000-byte message")
{
return (t_md5_perf(1000, desc));
}
T_FUNC(perf_1000000, "microbenchmark with 1,000,000-byte message")
{
return (t_md5_perf(1000000, desc));
}
#endif
/***************************************************************************
* Boilerplate
*/
int
t_prepare(int argc, char *argv[])
{
int i, n;
(void)argc;
(void)argv;
n = sizeof t_md5_vectors / sizeof t_md5_vectors[0];
for (i = 0; i < n; ++i)
t_add_test(t_md5_vector, &t_md5_vectors[i],
"RFC 1321 test vector %d", i + 1);
#if !defined(WITH_OPENSSL) && !defined(WITH_RSAREF)
/*
* Run test vector 7 (which is 80 characters long) 5 characters at
* a time. This tests a) appending data to an underfull block and
* b) appending more data to an underfull block than it has room
* for (since 64 % 5 != 0). Test vector 7 already exercised the
* code path for computing a block directly from source (without
* copying it in), and all the test vectors except vector 1
* exercised the general case of copying a small amount of data in
* without crossing the block boundary.
*/
t_add_test(t_md5_short_updates, &t_md5_vectors[6],
"multiple short updates");
// t_add_test(t_md5_partial
#endif
return (0);
}
void
t_cleanup(void)
{
}

329
t/t_rfc4648.c Normal file
View file

@ -0,0 +1,329 @@
/*-
* Copyright (c) 2013-2014 Universitetet i Oslo
* Copyright (c) 2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <cryb/rfc4648.h>
#include "t.h"
struct t_case {
const char *desc;
int (*func)(const char *, size_t, char *, size_t *);
const char *in; /* input string */
size_t ilen; /* input length */
const char *out; /* expected output string or NULL */
size_t blen; /* initial value for olen or 0 */
size_t olen; /* expected value for olen */
int ret; /* expected return value */
int err; /* expected errno if ret != 0 */
};
/* basic encoding / decoding */
#define T_ENCODE_N(N, i, o) \
{ "base"#N"_encode("#i")", b##N##enc, i, sizeof i - 1, \
o, sizeof o, sizeof o, 0, 0 }
#define T_DECODE_N(N, i, o) \
{ "base"#N"_decode("#i")", b##N##dec, i, sizeof i - 1, \
o, sizeof o - 1, sizeof o - 1, 0, 0 }
#define T_ENCODE(p, b32, b64) \
T_ENCODE_N(32, p, b32), T_ENCODE_N(64, p, b64)
#define T_DECODE(p, b32, b64) \
T_DECODE_N(32, b32, p), T_DECODE_N(64, b64, p)
/* roundtrip encoding tests */
#define T_ENCDEC_N(N, p, e) \
T_ENCODE_N(N, p, e), T_DECODE_N(N, e, p)
#define T_ENCDEC(p, b32, b64) \
T_ENCDEC_N(32, p, b32), T_ENCDEC_N(64, p, b64)
/* decoding failure */
#define T_DECODE_FAIL_N(N, e, i) \
{ "base"#N"_decode("#i")", b##N##dec, i, sizeof i - 1, \
NULL, 0, 0, -1, e }
#define T_DECODE_FAIL(e, b32, b64) \
T_DECODE_FAIL_N(32, e, b32), T_DECODE_FAIL_N(64, e, b64)
/* input string shorter than input length */
#define T_SHORT_INPUT_DEC(N, i) \
{ "base"#N"_decode (short input)", b##N##dec, i, sizeof i + 2, \
NULL, 0, base##N##_declen(sizeof i - 1), 0, 0 }
#define T_SHORT_INPUT() \
T_SHORT_INPUT_DEC(32, "AAAAAAAA"), \
T_SHORT_INPUT_DEC(64, "AAAA")
/* output string longer than output length */
#define T_LONG_OUTPUT_ENC(N, i) \
{ "base"#N"_enc (long output)", b##N##enc, i, sizeof i - 1, \
NULL, 1, base##N##_enclen(sizeof i - 1) + 1, -1, ENOSPC }
#define T_LONG_OUTPUT_DEC(N, i) \
{ "base"#N"_decode (long output)", b##N##dec, "AAAAAAAA", 8, \
NULL, 1, base##N##_declen(sizeof i - 1), -1, ENOSPC }
#define T_LONG_OUTPUT() \
T_LONG_OUTPUT_ENC(32, "foo"), \
T_LONG_OUTPUT_DEC(32, "AAAAAAAA"), \
T_LONG_OUTPUT_ENC(64, "foo"), \
T_LONG_OUTPUT_DEC(64, "AAAA")
static const char b64alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static const char b64complete[] = {
0x00, 0x10, 0x83, 0x10, 0x51, 0x87,
0x20, 0x92, 0x8b, 0x30, 0xd3, 0x8f,
0x41, 0x14, 0x93, 0x51, 0x55, 0x97,
0x61, 0x96, 0x9b, 0x71, 0xd7, 0x9f,
0x82, 0x18, 0xa3, 0x92, 0x59, 0xa7,
0xa2, 0x9a, 0xab, 0xb2, 0xdb, 0xaf,
0xc3, 0x1c, 0xb3, 0xd3, 0x5d, 0xb7,
0xe3, 0x9e, 0xbb, 0xf3, 0xdf, 0xbf,
0x00
};
static const char b32alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
static const char b32complete[] = {
0x00, 0x44, 0x32, 0x14, 0xc7,
0x42, 0x54, 0xb6, 0x35, 0xcf,
0x84, 0x65, 0x3a, 0x56, 0xd7,
0xc6, 0x75, 0xbe, 0x77, 0xdf,
0x00
};
static int
b32enc(const char *in, size_t ilen, char *out, size_t *olen)
{
return base32_encode((const uint8_t *)in, ilen, out, olen);
}
static int
b32dec(const char *in, size_t ilen, char *out, size_t *olen)
{
return base32_decode(in, ilen, (uint8_t *)out, olen);
}
static int
b64enc(const char *in, size_t ilen, char *out, size_t *olen)
{
return base64_encode((const uint8_t *)in, ilen, out, olen);
}
static int
b64dec(const char *in, size_t ilen, char *out, size_t *olen)
{
return base64_decode(in, ilen, (uint8_t *)out, olen);
}
static struct t_case t_cases[] = {
/* complete alphabet */
T_ENCDEC_N(32, b32complete, b32alphabet),
T_ENCDEC_N(64, b64complete, b64alphabet),
/* test vectors from RFC 4648 */
/* plain base32 base64 */
T_ENCDEC("", "", ""),
T_ENCDEC("f", "MY======", "Zg=="),
T_ENCDEC("fo", "MZXQ====", "Zm8="),
T_ENCDEC("foo", "MZXW6===", "Zm9v"),
T_ENCDEC("foob", "MZXW6YQ=", "Zm9vYg=="),
T_ENCDEC("fooba", "MZXW6YTB", "Zm9vYmE="),
T_ENCDEC("foobar", "MZXW6YTBOI======", "Zm9vYmFy"),
/* zeroes */
T_ENCDEC("\0\0\0", "AAAAA===", "AAAA"),
/* sloppy padding */
T_DECODE("f", "MY=", "Zg="),
T_DECODE("f", "MY", "Zg"),
/* whitespace */
/* plain base32 base64 */
T_DECODE("tst", "ORZX I===", "dH N0"),
T_DECODE("tst", "ORZX\tI===", "dH\tN0"),
T_DECODE("tst", "ORZX\rI===", "dH\rN0"),
T_DECODE("tst", "ORZX\nI===", "dH\nN0"),
/* invalid character in data */
T_DECODE_FAIL(EINVAL, "AA!AAAAAA", "AA!A"),
/* invalid character in padding */
T_DECODE_FAIL(EINVAL, "AAAAA==!", "AA=!"),
/* padding with no data */
T_DECODE_FAIL(EINVAL, "AAAAAAAA=", "AAAA="),
/* data after padding */
T_DECODE_FAIL(EINVAL, "AA=A", "AA=A"),
/* padding in the wrong place, or non-zero bits in padding */
T_DECODE_FAIL_N(32, EINVAL, "A======="),
T_DECODE_N (32, "AA======", "\x00"),
T_DECODE_FAIL_N(32, EINVAL, "AB======"),
T_DECODE_FAIL_N(32, EINVAL, "AC======"),
T_DECODE_FAIL_N(32, EINVAL, "AD======"),
T_DECODE_N (32, "AE======", "\x01"),
T_DECODE_FAIL_N(32, EINVAL, "AAA====="),
T_DECODE_N (32, "AAAA====", "\x00\x00"),
T_DECODE_FAIL_N(32, EINVAL, "AAAB===="),
T_DECODE_FAIL_N(32, EINVAL, "AAAC===="),
T_DECODE_FAIL_N(32, EINVAL, "AAAD===="),
T_DECODE_FAIL_N(32, EINVAL, "AAAE===="),
T_DECODE_FAIL_N(32, EINVAL, "AAAF===="),
T_DECODE_FAIL_N(32, EINVAL, "AAAG===="),
T_DECODE_FAIL_N(32, EINVAL, "AAAH===="),
T_DECODE_FAIL_N(32, EINVAL, "AAAI===="),
T_DECODE_FAIL_N(32, EINVAL, "AAAJ===="),
T_DECODE_FAIL_N(32, EINVAL, "AAAK===="),
T_DECODE_FAIL_N(32, EINVAL, "AAAL===="),
T_DECODE_FAIL_N(32, EINVAL, "AAAM===="),
T_DECODE_FAIL_N(32, EINVAL, "AAAN===="),
T_DECODE_FAIL_N(32, EINVAL, "AAAO===="),
T_DECODE_FAIL_N(32, EINVAL, "AAAP===="),
T_DECODE_N (32, "AAAQ====", "\x00\x01"),
T_DECODE_N (32, "AAAAA===", "\x00\x00\x00"),
T_DECODE_FAIL_N(32, EINVAL, "AAAAB==="),
T_DECODE_N (32, "AAAAC===", "\x00\x00\x01"),
T_DECODE_FAIL_N(32, EINVAL, "AAAAAA=="),
T_DECODE_N (32, "AAAAAAA=", "\x00\x00\x00\x00"),
T_DECODE_FAIL_N(32, EINVAL, "AAAAAAB="),
T_DECODE_FAIL_N(32, EINVAL, "AAAAAAC="),
T_DECODE_FAIL_N(32, EINVAL, "AAAAAAD="),
T_DECODE_FAIL_N(32, EINVAL, "AAAAAAE="),
T_DECODE_FAIL_N(32, EINVAL, "AAAAAAF="),
T_DECODE_FAIL_N(32, EINVAL, "AAAAAAG="),
T_DECODE_FAIL_N(32, EINVAL, "AAAAAAH="),
T_DECODE_N (32, "AAAAAAI=", "\x00\x00\x00\x01"),
T_DECODE_N (32, "AAAAAAAA", "\x00\x00\x00\x00\x00"),
T_DECODE_FAIL_N(64, EINVAL, "A==="),
T_DECODE_N (64, "AA==", "\x00"),
T_DECODE_FAIL_N(64, EINVAL, "AB=="),
T_DECODE_FAIL_N(64, EINVAL, "AC=="),
T_DECODE_FAIL_N(64, EINVAL, "AD=="),
T_DECODE_FAIL_N(64, EINVAL, "AE=="),
T_DECODE_FAIL_N(64, EINVAL, "AF=="),
T_DECODE_FAIL_N(64, EINVAL, "AG=="),
T_DECODE_FAIL_N(64, EINVAL, "AH=="),
T_DECODE_FAIL_N(64, EINVAL, "AI=="),
T_DECODE_FAIL_N(64, EINVAL, "AJ=="),
T_DECODE_FAIL_N(64, EINVAL, "AK=="),
T_DECODE_FAIL_N(64, EINVAL, "AL=="),
T_DECODE_FAIL_N(64, EINVAL, "AM=="),
T_DECODE_FAIL_N(64, EINVAL, "AN=="),
T_DECODE_FAIL_N(64, EINVAL, "AO=="),
T_DECODE_FAIL_N(64, EINVAL, "AP=="),
T_DECODE_N (64, "AQ==", "\x01"),
T_DECODE_N (64, "AAA=", "\x00\x00"),
T_DECODE_FAIL_N(64, EINVAL, "AAB="),
T_DECODE_FAIL_N(64, EINVAL, "AAC="),
T_DECODE_FAIL_N(64, EINVAL, "AAD="),
T_DECODE_N (64, "AAE=", "\x00\x01"),
/* various error conditions */
T_SHORT_INPUT(),
T_LONG_OUTPUT(),
};
/*
* Encoding test function
*/
static int
t_rfc4648(char **desc CRYB_UNUSED, void *arg)
{
struct t_case *t = arg;
char buf[256];
size_t len;
int ret;
len = t->blen ? t->blen : sizeof buf;
ret = t->func(t->in, t->ilen, buf, &len);
if (ret != t->ret) {
t_verbose("expected return code %d, got %d\n",
t->ret, ret);
return (0);
}
if (t->out && len != t->olen) {
t_verbose("expected output length %zu, got %zu\n",
t->olen, len);
return (0);
}
if (t->ret != 0 && errno != t->err) {
t_verbose("expected errno %d, got %d\n",
t->err, errno);
return (0);
}
if (t->ret == 0 && t->out && strncmp(buf, t->out, len) != 0) {
t_verbose("expected '%.*s' got '%.*s'\n",
(int)t->olen, t->out, (int)len, buf);
return (0);
}
return (1);
}
/*
* Generate the test plan
*/
int
t_prepare(int argc, char *argv[])
{
int i, n;
(void)argc;
(void)argv;
n = sizeof t_cases / sizeof t_cases[0];
for (i = 0; i < n; ++i)
t_add_test(t_rfc4648, &t_cases[i], t_cases[i].desc);
return (0);
}
/*
* Cleanup
*/
void
t_cleanup(void)
{
}

284
t/t_sha1.c Normal file
View file

@ -0,0 +1,284 @@
/*-
* Copyright (c) 2012 Universitetet i Oslo
* Copyright (c) 2012-2014 Dag-Erling Smørgrav
* 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 of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Dag-Erling Smørgrav <des@des.no>
* Sponsor: the University of Oslo
*
* $Id$
*/
#include "cryb/impl.h"
#include <err.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "t.h"
#if WITH_OPENSSL
#include <openssl/sha.h>
#define SHA1_DIGEST_LEN SHA_DIGEST_LENGTH
static void
t_sha1_complete(const void *msg, size_t msglen, uint8_t *digest)
{
SHA_CTX ctx;
SHA1_Init(&ctx);
SHA1_Update(&ctx, msg, msglen);
SHA1_Final(digest, &ctx);
}
#else
#include <cryb/sha1.h>
#define t_sha1_complete(msg, msglen, digest) \
sha1_complete(msg, msglen, digest)
#endif
static struct t_vector {
const char *desc;
const char *msg;
const uint8_t digest[SHA1_DIGEST_LEN];
} t_sha1_vectors[] = {
{
"zero-length message",
"",
{
0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d,
0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
0xaf, 0xd8, 0x07, 0x09,
}
},
{
"FIPS 180-2 A.1 (one-block message)",
"abc",
{
0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
0x9c, 0xd0, 0xd8, 0x9d,
}
},
{
/*
* This message is *just* long enough to necessitate a
* second block, which consists entirely of padding.
*/
"FIPS 180-2 A.2 (multi-block message)",
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
{
0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e,
0xba, 0xae, 0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5,
0xe5, 0x46, 0x70, 0xf1,
}
},
{
/*
* 1,000,000 x 'a', filled in by t_prepare()
*/
"FIPS 180-2 A.3 (long message)",
NULL,
{
0x34, 0xaa, 0x97, 0x3c, 0xd4, 0xc4, 0xda, 0xa4,
0xf6, 0x1e, 0xeb, 0x2b, 0xdb, 0xad, 0x27, 0x31,
0x65, 0x34, 0x01, 0x6f,
},
},
{
/*
* One of the MD5 test vectors, included for the "short
* update" test.
*/
"\"1234567890\"x8",
"1234567890123456789012345678901234567890"
"1234567890123456789012345678901234567890",
{
0x50, 0xab, 0xf5, 0x70, 0x6a, 0x15, 0x09, 0x90,
0xa0, 0x8b, 0x2c, 0x5e, 0xa4, 0x0f, 0xa0, 0xe5,
0x85, 0x55, 0x47, 0x32,
},
},
};
/*
* Unit test: compute the SHA1 sum of the specified string and compare it
* to the expected result.
*/
static int
t_sha1_vector(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t digest[SHA1_DIGEST_LEN];
char *msg;
if (vector->msg) {
t_sha1_complete(vector->msg, strlen(vector->msg), digest);
} else {
/* special case for FIPS test vector 3 */
if ((msg = malloc(1000000)) == NULL)
err(1, "malloc()");
memset(msg, 'a', 1000000);
t_sha1_complete(msg, 1000000, digest);
free(msg);
}
if (memcmp(digest, vector->digest, SHA1_DIGEST_LEN) != 0) {
t_verbose("expected ");
t_verbose_hex(vector->digest, SHA1_DIGEST_LEN);
t_verbose("\n");
t_verbose("got ");
t_verbose_hex(digest, SHA1_DIGEST_LEN);
t_verbose("\n");
return (0);
}
return (1);
}
#if !defined(WITH_OPENSSL) && !defined(WITH_RSAREF)
/*
* Various corner cases and error conditions
*/
static int
t_sha1_short_updates(char **desc CRYB_UNUSED, void *arg)
{
struct t_vector *vector = (struct t_vector *)arg;
uint8_t digest[SHA1_DIGEST_LEN];
sha1_ctx ctx;
int i, len;
sha1_init(&ctx);
len = strlen(vector->msg);
for (i = 0; i + 5 < len; i += 5)
sha1_update(&ctx, vector->msg + i, 5);
sha1_update(&ctx, vector->msg + i, len - i);
sha1_final(&ctx, digest);
return (memcmp(digest, vector->digest, SHA1_DIGEST_LEN) == 0);
}
#endif
#ifdef BENCHMARKS
/*
* Performance test: measure the time spent computing the SHA1 sum of a
* message of the specified length.
*/
#define T_PERF_ITERATIONS 1000
static int
t_sha1_perf(const char **desc, void *arg)
{
struct timespec ts, te;
unsigned long ns;
uint8_t digest[SHA1_DIGEST_LEN];
char *msg, *comment;
if ((msg = calloc(1, msglen)) == NULL)
err(1, "calloc()");
clock_gettime(CLOCK_MONOTONIC_PRECISE, &ts);
for (int i = 0; i < T_PERF_ITERATIONS; ++i)
t_sha1_complete(msg, msglen, digest);
clock_gettime(CLOCK_MONOTONIC_PRECISE, &te);
free(msg);
ns = te.tv_sec * 1000000000LU + te.tv_nsec;
ns -= ts.tv_sec * 1000000000LU + ts.tv_nsec;
asprintf(&comment, "%zu bytes: %d iterations in %'lu ns",
msglen, T_PERF_ITERATIONS, ns);
if (comment == NULL)
err(1, "asprintf()");
*desc = (const char *)comment;
return (1);
}
#endif
#ifdef BENCHMARKS
/*
* Microbenchmarks
*/
T_FUNC(perf_0, "microbenchmark with empty message")
{
return (t_sha1_perf(0, desc));
}
T_FUNC(perf_1000, "microbenchmark with 1,000-byte message")
{
return (t_sha1_perf(1000, desc));
}
T_FUNC(perf_1000000, "microbenchmark with 1,000,000-byte message")
{
return (t_sha1_perf(1000000, desc));
}
#endif
/***************************************************************************
* Boilerplate
*/
int
t_prepare(int argc, char *argv[])
{
int i, n;
(void)argc;
(void)argv;
n = sizeof t_sha1_vectors / sizeof t_sha1_vectors[0];
for (i = 0; i < n; ++i)
t_add_test(t_sha1_vector, &t_sha1_vectors[i],
t_sha1_vectors[i].desc);
#if !defined(WITH_OPENSSL) && !defined(WITH_RSAREF)
/*
* Run test vector 5 (md5 test vector 7, which is 80 characters
* long) 5 characters at a time. This tests a) appending data to
* an underfull block and b) appending more data to an underfull
* block than it has room for (since 64 % 5 != 0). Test vector 4
* and 5 already exercised the code path for computing a block
* directly from source (without copying it in), and all the test
* vectors except vector 1 exercised the general case of copying a
* small amount of data in without crossing the block boundary.
*/
t_add_test(t_sha1_short_updates, &t_sha1_vectors[4],
"multiple short updates");
#endif
return (0);
}
void
t_cleanup(void)
{
}

21
tools/setprops.sh Executable file
View file

@ -0,0 +1,21 @@
#!/bin/sh
istext() {
local mimetype=$(svn propget svn:mime-type "$1" 2>/dev/null)
[ -z "$mimetype" ] || expr "$mimetype" : '^text/.' >/dev/null
}
(svn list -R ; svn stat | awk '$1 == "A" { print $2 }') | sort -u |
while read f ; do
[ -f "$f" ] || continue
istext "$f" || continue
case $f in
*.sh|*.pl)
svn propset svn:executable \* $f
;&
*)
svn propset eol-style native $f
svn propset svn:keywords Id $f
;;
esac
done