/*
*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Yokogawa Electric Corporation,
* YDC Corporation, IPA (Information-technology Promotion Agency, Japan).
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions and disclaimer are agreed and accepted by the user:
*
* 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. Neither the names of the copyrighters, the name of the project which
* is related to this software (hereinafter referred to as "project") nor
* the names of the contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 4. No merchantable use may be permitted without prior written
* notification to the copyrighters. However, using this software for the
* purpose of testing or evaluating any products including merchantable
* products may be permitted without any notification to the copyrighters.
*
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHTERS, THE PROJECT AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING
* BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHTERS, THE PROJECT 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.
*
* $TAHI: v6eval/bin/sigcomp/sigcomp.c,v 1.16 2005/05/27 11:40:19 akisada Exp $
*
*/
#include <stdio.h>
#include <string.h>
#include <libgen.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#ifdef DEBUG
#ifndef dbg
#define dbg(stream, fmt, args...) \
{ \
if(stream) { \
fprintf(stream, "dbg[%d]: %s: %d: %s(): " fmt, \
getpid(), __FILE__, __LINE__, __FUNCTION__, ##args); \
} \
}
#endif // dbg
#ifndef dmp
#define dmp(stream, name, buf, buflen) \
{ \
if(stream) { \
unsigned char *buffer = (unsigned char *)buf; \
unsigned int length = (unsigned int)buflen; \
unsigned int d = 0; \
fprintf(stream, "dmp[%d]: %s: %d: %s(): %s: buffer: ", \
getpid(), __FILE__, __LINE__, __FUNCTION__, name); \
for(d = 0; d < length; d ++) { \
fprintf(stream, "%02x", buffer[d]); \
} \
fputc('\n', stream); \
fprintf(stream, "dmp[%d]: %s: %d: %s(): %s: length: %d\n", \
getpid(), __FILE__, __LINE__, __FUNCTION__, name, length); \
} \
}
#endif // dmp
#endif // DEBUG
typedef unsigned char bool;
static const bool false = 0;
static const bool true = 1;
static const char *prog = NULL;
static bool xxxflag;
static const bool sigcomp_main(const char *const, const char *const,
const char *const, const char *const, const char *const);
static const bool sigcomp_return(const bool, BIGNUM *, BIGNUM *, BIGNUM *);
static const bool sigcomp_sign(const EVP_MD *const, const BIGNUM *const,
const BIGNUM *const, const char *const);
static void sigcomp_sign_dump(const unsigned char *const, int,
const unsigned char *const, int, const unsigned char *const, int);
static const bool sigcomp_sign_return(const bool,
unsigned char *, unsigned char *, unsigned char *, EVP_PKEY *);
static const bool sigcomp_vrfy(const EVP_MD *const, const BIGNUM *const,
const BIGNUM *const, const BIGNUM *const, const char *const);
static void sigcomp_vrfy_dump(const bool, const unsigned char *const, int,
const unsigned char *const, int, const unsigned char *const, int,
const unsigned char *const, int);
static const bool sigcomp_vrfy_return(const bool,
unsigned char *, unsigned char *, unsigned char *, unsigned char *,
EVP_PKEY *);
static const EVP_MD *evp_md_with_algorithm(const char *const,
const char *const);
static void openssl_strerror(const char *const);
static void usage(void);
int
main(int argc, char **argv, char **envp)
{
#if 0
const char *algorithm = NULL;
#else
const char *algorithm = "md5";
#endif
const char *key = NULL;
const char *msg = NULL;
const char *signature = NULL;
#if 0
const char *type = NULL;
#else
const char *type = "rsa";
#endif
xxxflag = false;
if(!(prog = basename(argv[0]))) {
fprintf(stderr, "err: basename: %s -- %s\n",
strerror(errno), argv[0]);
return(-1);
/* NOTREACHED */
}
{
int ch = 0;
#if 0
while((ch = getopt(argc, argv, "a:k:m:s:t:@")) != -1) {
#else
while((ch = getopt(argc, argv, "k:m:s:@")) != -1) {
#endif
switch (ch) {
#if 0
case 'a':
algorithm = optarg;
break;
#endif
case 'k':
key = optarg;
break;
case 'm':
msg = optarg;
break;
case 's':
signature = optarg;
break;
#if 0
case 't':
type = optarg;
break;
#endif
case '@':
xxxflag = true;
break;
default:
usage();
/* NOTREACHED */
break;
}
}
argc -= optind;
argv += optind;
}
if(argc || !algorithm || !key || !msg || !type) {
usage();
/* NOTREACHED */
}
return(sigcomp_main(algorithm, key, msg, signature, type)? 0: -1);
/* NOTREACHED */
}
static const bool
sigcomp_main(const char *const algorithm, const char *const key,
const char *const msg, const char *const signature,
const char *const type)
{
const EVP_MD *evp_md = NULL;
BIGNUM *bn_key = NULL;
BIGNUM *bn_msg = NULL;
BIGNUM *bn_signature = NULL;
ERR_load_crypto_strings();
if(!(evp_md = evp_md_with_algorithm(type, algorithm))) {
fprintf(stderr, "err: algorithm: %s -- "
"unknown algorithm for %s\n", algorithm, type);
return(sigcomp_return(false, bn_key, bn_msg, bn_signature));
}
/* key -> bn_key */
if(!(bn_key = BN_new())) {
openssl_strerror("BN_new");
return(sigcomp_return(false, bn_key, bn_msg, bn_signature));
}
if(!BN_hex2bn(&bn_key, (const char *)key)) {
openssl_strerror("BN_hex2bn");
return(sigcomp_return(false, bn_key, bn_msg, bn_signature));
}
/* msg -> bn_msg */
if(!(bn_msg = BN_new())) {
openssl_strerror("BN_new");
return(sigcomp_return(false, bn_key, bn_msg, bn_signature));
}
if(!BN_hex2bn(&bn_msg, (const char *)msg)) {
openssl_strerror("BN_hex2bn");
return(sigcomp_return(false, bn_key, bn_msg, bn_signature));
}
if(signature) {
/* signature -> bn_signature */
if(!(bn_signature = BN_new())) {
openssl_strerror("BN_new");
return(sigcomp_return(false,
bn_key, bn_msg, bn_signature));
}
if(!BN_hex2bn(&bn_signature, (const char *)signature)) {
openssl_strerror("BN_hex2bn");
return(sigcomp_return(false,
bn_key, bn_msg, bn_signature));
}
if(!sigcomp_vrfy(evp_md, bn_key, bn_msg, bn_signature, type)) {
return(sigcomp_return(false,
bn_key, bn_msg, bn_signature));
}
} else {
if(!sigcomp_sign(evp_md, bn_key, bn_msg, type)) {
return(sigcomp_return(false,
bn_key, bn_msg, bn_signature));
}
}
return(sigcomp_return(true, bn_key, bn_msg, bn_signature));
}
static const bool
sigcomp_return(const bool code,
BIGNUM *bn_key, BIGNUM *bn_msg, BIGNUM *bn_signature)
{
if(bn_signature) {
BN_free(bn_signature); bn_signature = NULL;
}
if(bn_msg) {
BN_free(bn_msg); bn_msg = NULL;
}
if(bn_key) {
BN_free(bn_key); bn_key = NULL;
}
return(code);
}
static const bool
sigcomp_sign(const EVP_MD *const evp_md, const BIGNUM *const bn_key,
const BIGNUM *const bn_msg, const char *const type)
{
EVP_PKEY *pkey = NULL;
unsigned char *key = NULL;
unsigned char *msg = NULL;
unsigned char *signature = NULL;
unsigned char *ptr = NULL;
int keylen = 0;
int msglen = 0;
int signaturelen = 0;
int padding = 0;
/* bn_key -> key */
if(!(keylen = BN_num_bytes(bn_key))) {
openssl_strerror("BN_num_bytes");
return(sigcomp_sign_return(false, key, msg, signature, pkey));
}
if(!(key = (unsigned char *)malloc(keylen))) {
fprintf(stderr, "err: malloc: %s\n", strerror(errno));
return(sigcomp_sign_return(false, key, msg, signature, pkey));
}
if(BN_bn2bin(bn_key, key) != keylen) {
openssl_strerror("BN_bn2bin");
return(sigcomp_sign_return(false, key, msg, signature, pkey));
}
#ifdef DEBUG
dmp(stderr, "key", key, keylen);
#endif // DEBUG
/* bn_msg -> msg */
if(!(msglen = BN_num_bytes(bn_msg))) {
openssl_strerror("BN_num_bytes");
return(sigcomp_sign_return(false, key, msg, signature, pkey));
}
if(!(msg = (unsigned char *)malloc(msglen))) {
fprintf(stderr, "err: malloc: %s\n", strerror(errno));
return(sigcomp_sign_return(false, key, msg, signature, pkey));
}
if(BN_bn2bin(bn_msg, msg) != msglen) {
openssl_strerror("BN_bn2bin");
return(sigcomp_sign_return(false, key, msg, signature, pkey));
}
#ifdef DEBUG
dmp(stderr, "msg", msg, msglen);
#endif // DEBUG
ptr = key;
for( ; ; ) {
if(!strcmp(type, "rsa")) {
if(!(pkey = d2i_PrivateKey(EVP_PKEY_RSA,
NULL, &ptr, keylen))) {
openssl_strerror("d2i_PrivateKey");
return(sigcomp_sign_return(false,
key, msg, signature, pkey));
}
signaturelen = RSA_size(pkey->pkey.rsa);
padding = RSA_PKCS1_PADDING;
break;
}
if(!strcmp(type, "dsa")) {
if(!(pkey = d2i_PrivateKey(EVP_PKEY_DSA,
NULL, &ptr, keylen))) {
openssl_strerror("d2i_PrivateKey");
return(sigcomp_sign_return(false,
key, msg, signature, pkey));
}
fprintf(stderr, "err: type: %s -- not implemented\n",
type);
return(sigcomp_sign_return(false,
key, msg, signature, pkey));
break;
}
fprintf(stderr, "err: type: %s -- unknown type\n",
type);
return(sigcomp_sign_return(false, key, msg, signature, pkey));
/* NOTREACHED */
}
if(!(signature = (unsigned char *)malloc(signaturelen))) {
fprintf(stderr, "err: malloc: %s\n", strerror(errno));
return(sigcomp_sign_return(false, key, msg, signature, pkey));
}
RSA_private_encrypt(msglen, msg, signature, pkey->pkey.rsa, padding);
#ifdef DEBUG
dmp(stderr, "signature", signature, signaturelen);
#endif // DEBUG
sigcomp_sign_dump(key, keylen, msg, msglen, signature, signaturelen);
return(sigcomp_sign_return(true, key, msg, signature, pkey));
}
static void
sigcomp_sign_dump(const unsigned char *const key, int keylen,
const unsigned char *const msg, int msglen,
const unsigned char *const signature, int signaturelen)
{
int d = 0;
if(xxxflag) {
#if 0 /* needless */
for(d = 0; d < msglen; d ++) {
printf("%02x", msg[d]);
}
#endif
for(d = 0; d < signaturelen; d ++) {
printf("%02x", signature[d]);
}
printf("\n");
return;
}
printf("log:SigCompSign_Results (length:%d)\n",
keylen + msglen + signaturelen);
printf("log:| PrivateKey (length:%d)\n", keylen);
printf("log:| | data = ");
for(d = 0; d < keylen; d ++) {
printf("%02x", key[d]);
}
printf("\n");
printf("log:| Message (length:%d)\n", msglen);
printf("log:| | data = ");
for(d = 0; d < msglen; d ++) {
printf("%02x", msg[d]);
}
printf("\n");
printf("log:| Signature (length:%d)\n",
signaturelen);
printf("log:| | data = ");
for(d = 0; d < signaturelen; d ++) {
printf("%02x", signature[d]);
}
printf("\n");
return;
}
static const bool
sigcomp_sign_return(const bool code,
unsigned char *key, unsigned char *msg, unsigned char *signature,
EVP_PKEY *pkey)
{
if(pkey) {
EVP_PKEY_free(pkey); pkey = NULL;
}
if(signature) {
free(signature); signature = NULL;
}
if(msg) {
free(msg); msg = NULL;
}
if(key) {
free(key); key = NULL;
}
return(code);
}
static const bool
sigcomp_vrfy(const EVP_MD *const evp_md, const BIGNUM *const bn_key,
const BIGNUM *const bn_msg,
const BIGNUM *const bn_signature, const char *const type)
{
EVP_PKEY *pkey = NULL;
unsigned char *key = NULL;
unsigned char *msg = NULL;
unsigned char *signature = NULL;
unsigned char *to = NULL;
unsigned char *ptr = NULL;
int keylen = 0;
int msglen = 0;
int signaturelen = 0;
int tolen = 0;
int padding = 0;
bool compare = true;
/* bn_key -> key */
if(!(keylen = BN_num_bytes(bn_key))) {
openssl_strerror("BN_num_bytes");
return(sigcomp_vrfy_return(false,
key, msg, signature, to, pkey));
}
if(!(key = (unsigned char *)malloc(keylen))) {
fprintf(stderr, "err: malloc: %s\n", strerror(errno));
return(sigcomp_vrfy_return(false,
key, msg, signature, to, pkey));
}
if(BN_bn2bin(bn_key, key) != keylen) {
openssl_strerror("BN_bn2bin");
return(sigcomp_vrfy_return(false,
key, msg, signature, to, pkey));
}
#ifdef DEBUG
dmp(stderr, "key", key, keylen);
#endif // DEBUG
/* bn_msg -> msg */
if(!(msglen = BN_num_bytes(bn_msg))) {
openssl_strerror("BN_num_bytes");
return(sigcomp_vrfy_return(false,
key, msg, signature, to, pkey));
}
if(!(msg = (unsigned char *)malloc(msglen))) {
fprintf(stderr, "err: malloc: %s\n", strerror(errno));
return(sigcomp_vrfy_return(false,
key, msg, signature, to, pkey));
}
if(BN_bn2bin(bn_msg, msg) != msglen) {
openssl_strerror("BN_bn2bin");
return(sigcomp_vrfy_return(false,
key, msg, signature, to, pkey));
}
#ifdef DEBUG
dmp(stderr, "msg", msg, msglen);
#endif // DEBUG
/* bn_signature -> signature */
if(!(signaturelen = BN_num_bytes(bn_signature))) {
openssl_strerror("BN_num_bytes");
return(sigcomp_vrfy_return(false,
key, msg, signature, to, pkey));
}
if(!(signature = (unsigned char *)malloc(signaturelen))) {
fprintf(stderr, "err: malloc: %s\n", strerror(errno));
return(sigcomp_vrfy_return(false,
key, msg, signature, to, pkey));
}
if(BN_bn2bin(bn_signature, signature) != signaturelen) {
openssl_strerror("BN_bn2bin");
return(sigcomp_vrfy_return(false,
key, msg, signature, to, pkey));
}
#ifdef DEBUG
dmp(stderr, "signature", signature, signaturelen);
#endif // DEBUG
ptr = key;
for( ; ; ) {
if(!strcmp(type, "rsa")) {
if(!(pkey = d2i_PublicKey(EVP_PKEY_RSA,
NULL, &ptr, keylen))) {
openssl_strerror("d2i_PublicKey");
return(sigcomp_vrfy_return(false,
key, msg, signature, to, pkey));
}
tolen = RSA_size(pkey->pkey.rsa);
padding = RSA_PKCS1_PADDING;
break;
}
if(!strcmp(type, "dsa")) {
if(!(pkey = d2i_PublicKey(EVP_PKEY_DSA,
NULL, &ptr, keylen))) {
openssl_strerror("d2i_PublicKey");
return(sigcomp_vrfy_return(false,
key, msg, signature, to, pkey));
}
fprintf(stderr, "err: type: %s -- not implemented\n",
type);
return(sigcomp_vrfy_return(false,
key, msg, signature, to, pkey));
/* NOTREACHED */
break;
}
fprintf(stderr, "err: type: %s -- unknown type\n",
type);
return(sigcomp_vrfy_return(false,
key, msg, signature, to, pkey));
/* NOTREACHED */
}
if(!(to = (unsigned char *)malloc(tolen))) {
fprintf(stderr, "err: malloc: %s\n", strerror(errno));
return(sigcomp_vrfy_return(false,
key, msg, signature, to, pkey));
}
if(RSA_public_decrypt(signaturelen,
signature, to, pkey->pkey.rsa, padding) < 0) {
openssl_strerror("RSA_public_decrypt");
return(sigcomp_vrfy_return(true,
key, msg, signature, to, pkey));
}
if(memcmp(msg, to, msglen)) {
compare = false;
}
sigcomp_vrfy_dump(compare, key, keylen,
msg, msglen, signature, signaturelen, to, tolen);
return(sigcomp_vrfy_return(true, key, msg, signature, to, pkey));
}
static void
sigcomp_vrfy_dump(const bool code, const unsigned char *const key, int keylen,
const unsigned char *const msg, int msglen,
const unsigned char *const signature, int signaturelen,
const unsigned char *const to, int tolen)
{
int d = 0;
printf("log:SigCompVrfy_Results (length:%d)\n",
keylen + msglen + signaturelen + tolen);
printf("log:| PublicKey (length:%d)\n", keylen);
printf("log:| | data = ");
for(d = 0; d < keylen; d ++) {
printf("%02x", key[d]);
}
printf("\n");
printf("log:| Message (length:%d)\n", msglen);
printf("log:| | data = ");
for(d = 0; d < msglen; d ++) {
printf("%02x", msg[d]);
}
printf("\n");
printf("log:| Signature (length:%d)\n",
signaturelen + tolen);
printf("log:| | status = %s\n",
code? "true": "false");
printf("log:| | Encrypted (length:%d)\n",
signaturelen);
printf("log:| | | data = ");
for(d = 0; d < signaturelen; d ++) {
printf("%02x", signature[d]);
}
printf("\n");
printf("log:| | Decrypted (length:%d)\n", tolen);
printf("log:| | | data = ");
for(d = 0; d < tolen; d ++) {
printf("%02x", to[d]);
}
printf("\n");
return;
}
static const bool
sigcomp_vrfy_return(const bool code,
unsigned char *key, unsigned char *msg, unsigned char *signature,
unsigned char *to, EVP_PKEY *pkey)
{
if(pkey) {
EVP_PKEY_free(pkey); pkey = NULL;
}
if(to) {
free(to); to = NULL;
}
if(signature) {
free(signature); signature = NULL;
}
if(msg) {
free(msg); msg = NULL;
}
if(key) {
free(key); key = NULL;
}
return(code);
}
static const EVP_MD *
evp_md_with_algorithm(const char *const type, const char *const algorithm)
{
const EVP_MD *evp_md = NULL;
bool dsa = false;
bool rsa = false;
for( ; ; ) {
if(!strcmp(type, "dsa")) {
dsa = true;
break;
}
if(!strcmp(type, "rsa")) {
rsa = true;
break;
}
break;
}
for( ; ; ) {
if(dsa && !strcmp(algorithm, "dss1")) {
evp_md = EVP_dss1();
break;
}
if(rsa && !strcmp(algorithm, "md2")) {
evp_md = EVP_md2();
break;
}
if(rsa && !strcmp(algorithm, "md4")) {
evp_md = EVP_md4();
break;
}
if(rsa && !strcmp(algorithm, "md5")) {
evp_md = EVP_md5();
break;
}
if(rsa && !strcmp(algorithm, "mdc2")) {
evp_md = EVP_mdc2();
break;
}
if(rsa && !strcmp(algorithm, "ripemd160")) {
evp_md = EVP_ripemd160();
break;
}
if(rsa && !strcmp(algorithm, "sha1")) {
evp_md = EVP_sha1();
break;
}
break;
}
return(evp_md);
}
static void
openssl_strerror(const char *const label)
{
unsigned long code = 0;
while((code = ERR_get_error())) {
fprintf(stderr, "err: %s: %s\n",
label, ERR_error_string(code, NULL));
}
return;
}
static void
usage(void)
{
#if 0
fprintf(stderr,
"err: usage: %s -a algorithm -k key -m msg -t type\n", prog);
fprintf(stderr,
"err: %s -a algorithm -k key -m msg -s signature "
"-t type\n", prog);
fprintf(stderr, "err: \n");
fprintf(stderr, "err: algorithm: dss1\n");
fprintf(stderr, "err: type: dsa\n");
fprintf(stderr, "err: \n");
fprintf(stderr, "err: algorithm: "
"md2, md4, md5, sha1, mdc2, ripemd160\n");
fprintf(stderr, "err: type: rsa\n");
fprintf(stderr, "err: \n");
#else
fprintf(stderr,
"err: usage: %s -k privatekey -m msg\n", prog);
fprintf(stderr,
"err: %s -k publickey -m msg -s signature\n", prog);
#endif
exit(-1);
/* NOTREACHED */
return;
}
syntax highlighted by Code2HTML, v. 0.9.1