/* ppp-crypto.c - Generic API for access to crypto/digest functions.
*
* Copyright (c) 2022 Eivind Næss. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void PPP_MD_CTX_free(PPP_MD_CTX* ctx)
{
if (ctx) {
if (ctx->md.clean_fn) {
ctx->md.clean_fn(ctx);
}
free(ctx);
}
}
int PPP_DigestInit(PPP_MD_CTX *ctx, const PPP_MD *type)
{
int ret = 0;
if (ctx) {
ctx->md = *type;
if (ctx->md.init_fn) {
ret = ctx->md.init_fn(ctx);
if (!ret) {
PPP_crypto_error("Could not initialize digest");
}
}
}
return ret;
}
int PPP_DigestUpdate(PPP_MD_CTX *ctx, const void *data, size_t length)
{
int ret = 0;
if (ctx && ctx->md.update_fn) {
ret = ctx->md.update_fn(ctx, data, length);
if (!ret) {
PPP_crypto_error("Could not update digest");
}
}
return ret;
}
int PPP_DigestFinal(PPP_MD_CTX *ctx, unsigned char *out, unsigned int *outlen)
{
int ret = 0;
if (ctx && ctx->md.final_fn) {
ret = ctx->md.final_fn(ctx, out, outlen);
if (!ret) {
PPP_crypto_error("Could not perform final digest");
}
}
return ret;
}
int PPP_CipherInit(PPP_CIPHER_CTX *ctx, const PPP_CIPHER *cipher, const unsigned char *key, const unsigned char *iv, int encr)
{
int ret = 0;
if (ctx && cipher) {
ret = 1;
ctx->is_encr = encr;
ctx->cipher = *cipher;
if (ctx->cipher.init_fn) {
ret = ctx->cipher.init_fn(ctx, key, iv);
if (!ret) {
PPP_crypto_error("Could not initialize cipher");
}
}
}
return ret;
}
int PPP_CipherUpdate(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl)
{
int ret = 0;
if (ctx && ctx->cipher.update_fn) {
ret = ctx->cipher.update_fn(ctx, out, outl, in, inl);
if (!ret) {
PPP_crypto_error("Could not perform crypto operation");
}
}
return ret;
}
int PPP_CipherFinal(PPP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
{
int ret = 0;
if (ctx && ctx->cipher.final_fn) {
ret = ctx->cipher.final_fn(ctx, out, outl);
if (!ret) {
PPP_crypto_error("Could not perform final crypto operation");
}
}
return ret;
}
void
PPP_crypto_error(char *fmt, ...)
{
va_list args;
char buf[1024];
int len = sizeof(buf);
int off = 0;
int err = 0;
va_start(args, fmt);
off = vsnprintf(buf, len, fmt, args);
va_end(args);