/*- * Copyright (c) 2003 Allan Saddi * 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. * * THIS SOFTWARE IS PROVIDED BY ALLAN SADDI AND HIS 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 ALLAN SADDI OR HIS 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. * * $Id: crypto.c 930 2003-12-18 08:43:05Z asaddi $ */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #ifdef YAFIC_CRYPTO #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "crypto.h" #ifndef lint static const char rcsid[] = "$Id: crypto.c 930 2003-12-18 08:43:05Z asaddi $"; #endif /* !lint */ static EVP_PKEY *pkey; static void opensslError (const char *what) { fprintf (stderr, "%s: %s: %s\n", prog, what, ERR_reason_error_string (ERR_get_error ())); exit (1); } static int pass_cb (char *buf, int size, int rwflag, void *u) { char prompt[256]; char *pass; snprintf (prompt, sizeof (prompt), "Enter pass phrase for %s: ", (char *) u); pass = getpass (prompt); strlcpy (buf, pass, size); return strlen (buf); } void LoadKey (const char *filename, int pubkey) { FILE *f; if ((f = fopen (filename, "r"))) { if (pubkey) pkey = PEM_read_PUBKEY(f, NULL, pass_cb, (void *) filename); else pkey = PEM_read_PrivateKey(f, NULL, pass_cb, (void *) filename); fclose (f); if (pkey) return; opensslError (filename); } yaficError (filename); } void SignFile (int fd, const char *filename, const char *sigfile) { const EVP_MD *mdType; EVP_MD_CTX ctx; ssize_t len; unsigned char *sig = NULL; unsigned int sigLen; int f; char *tsigfile = NULL; if (!pkey) return; mdType = EVP_PKEY_type (pkey->type) == EVP_PKEY_DSA ? EVP_dss1 () : EVP_sha1 (); if (!sigfile) { int tlen = strlen (filename) + 4 + 1; tsigfile = mymalloc (tlen); strcpy (tsigfile, filename); strcat (tsigfile, ".sig"); sigfile = tsigfile; } #ifdef HAVE_EVP_MD_CTX_INIT EVP_MD_CTX_init (&ctx); #endif #ifdef EVP_DIGESTINIT_VOID EVP_SignInit (&ctx, mdType); #else if (!EVP_SignInit (&ctx, mdType)) opensslError ("EVP_SignInit"); #endif while ((len = read (fd, HashBuffer, HASH_BUFFER_SIZE)) > 0) { #ifdef EVP_DIGESTINIT_VOID EVP_SignUpdate (&ctx, HashBuffer, len); #else if (!EVP_SignUpdate (&ctx, HashBuffer, len)) opensslError ("EVP_SignUpdate"); #endif } if (len < 0) yaficError (filename); sig = mymalloc (EVP_PKEY_size (pkey)); if (EVP_SignFinal (&ctx, sig, &sigLen, pkey)) { if ((f = open (sigfile, O_CREAT|O_WRONLY|O_TRUNC, 0600)) != -1) { if (write (f, sig, sigLen) != sigLen) yaficError (sigfile); close (f); } else yaficError (sigfile); } else opensslError ("EVP_SignFinal"); if (sig) free (sig); if (tsigfile) free (tsigfile); #ifdef HAVE_EVP_MD_CTX_CLEANUP EVP_MD_CTX_cleanup (&ctx); #endif } void VerifyFile (int fd, const char *filename, const char *sigfile) { const EVP_MD *mdType; EVP_MD_CTX ctx; ssize_t len; unsigned char *sig = NULL; int f; int ret; char *tsigfile = NULL; if (!pkey) return; mdType = EVP_PKEY_type (pkey->type) == EVP_PKEY_DSA ? EVP_dss1 () : EVP_sha1 (); if (!sigfile) { int tlen = strlen (filename) + 4 + 1; tsigfile = mymalloc (tlen); strcpy (tsigfile, filename); strcat (tsigfile, ".sig"); sigfile = tsigfile; } fprintf (stderr, "Verifying %s: ", filename); fflush (stderr); #ifdef HAVE_EVP_MD_CTX_INIT EVP_MD_CTX_init (&ctx); #endif #ifdef EVP_DIGESTINIT_VOID EVP_VerifyInit (&ctx, mdType); #else if (!EVP_VerifyInit (&ctx, mdType)) { fprintf (stderr, "Error\n"); opensslError ("EVP_VerifyInit"); } #endif while ((len = read (fd, HashBuffer, HASH_BUFFER_SIZE)) > 0) { #ifdef EVP_DIGESTINIT_VOID EVP_VerifyUpdate (&ctx, HashBuffer, len); #else if (!EVP_VerifyUpdate (&ctx, HashBuffer, len)) { fprintf (stderr, "Error\n"); opensslError ("EVP_SignUpdate"); } #endif } if (len < 0) { fprintf (stderr, "Error\n"); yaficError (filename); } sig = mymalloc (EVP_PKEY_size (pkey)); if ((f = open (sigfile, O_RDONLY)) != -1) { if ((len = read (f, sig, EVP_PKEY_size (pkey))) < 0) { fprintf (stderr, "Error\n"); yaficError (sigfile); } close (f); ret = EVP_VerifyFinal (&ctx, sig, len, pkey); if (ret < 0) { fprintf (stderr, "Error\n"); opensslError ("EVP_VerifyFinal"); } if (ret) fprintf (stderr, "OK\n"); else { fprintf (stderr, "Fail\n"); exit (3); } } else { fprintf (stderr, "Error\n"); yaficError (sigfile); } if (sig) free (sig); if (tsigfile) free (tsigfile); #ifdef HAVE_EVP_MD_CTX_CLEANUP EVP_MD_CTX_cleanup (&ctx); #endif } const char * KeyTypeStr (void) { static char buf[64]; if (pkey) { int bits = EVP_PKEY_bits (pkey); int type = EVP_PKEY_type (pkey->type); switch (type) { case EVP_PKEY_RSA: snprintf (buf, sizeof (buf), "%d-bit rsa", bits); return buf; case EVP_PKEY_DSA: snprintf (buf, sizeof (buf), "%d-bit dsa", bits); return buf; } } else return "none"; return "unsupported"; } void CleanCrypto (void) { ERR_free_strings (); EVP_cleanup (); } void InitCrypto (void) { OpenSSL_add_all_algorithms (); ERR_load_crypto_strings (); } #endif /* YAFIC_CRYPTO */