Hi!

Due to great demand, I made this simple program that analyze let's call
the 'SPKAC' files and can return some info. Here the help:

        $ openssl spkac
        usage: spkac args
        
         -in infile  - Input file [required]
         -verbose    - Print a lot of info lines
         -keysize    - Print SPKAC public key size
         -verify     - Verify SPKAC public key signature
         -noout      - Does not print hex value of public key

example:

        $ openssl spkac -in request -keysize -verify -noout

        Key Size is 512
        Signature ok
        
        $ openssl spkac -in request
        SPKAC Public Key = {
        0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00, ...};

I think it is useful, and I hope you'll include in the next SNAP of OpenSSL.
(Please let me know whatever will be your decision).


Installation of this program (for who wants to test it):
========================================================

Build your OpenSSL 0.9.4 as normal. Now go to the apps/ dir. Copy the spkac.c
file there. Edit the Makefile and add let's say after pkcs8/pkcs8.c/pkcs8.o
spkca/spkca.c/spkac.o rispectively. Now edit the progs.h file and add the
following (lines are not really important if you know what you are doing):

at line 31:

        extern int spkac_main(int argc,char *argv[]);

and at line 59:

        {FUNC_TYPE_GENERAL,"spkac",spkac_main},

I think this is all. Now simple do:

        $ make
        $ make install

and you should be set, just try the program and please report bugs/enhancements
you might want to add.

C'you,

        Massimiliano Pala ([EMAIL PROTECTED])

P.S.: Please if you know a simpler installation method, report it (either to me
and the list). Thanks!
/* apps/spkac.c */
/* Copyright (C) 1995-1998 Eric Young ([EMAIL PROTECTED])
 * All rights reserved.
 *
 * This package is an SSL implementation written
 * by Eric Young ([EMAIL PROTECTED]).
 * The implementation was written so as to conform with Netscapes SSL.
 * 
 * This library is free for commercial and non-commercial use as long as
 * the following conditions are aheared to.  The following conditions
 * apply to all code found in this distribution, be it the RC4, RSA,
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 * included with this distribution is covered by the same copyright terms
 * except that the holder is Tim Hudson ([EMAIL PROTECTED]).
 * 
 * Copyright remains Eric Young's, and as such any Copyright notices in
 * the code are not to be removed.
 * If this package is used in a product, Eric Young should be given attribution
 * as the author of the parts of the library used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 * 
 * 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 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. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    "This product includes cryptographic software written by
 *     Eric Young ([EMAIL PROTECTED])"
 *    The word 'cryptographic' can be left out if the rouines from the library
 *    being used are not cryptographic related :-).
 * 4. If you include any Windows specific code (or a derivative thereof) from 
 *    the apps directory (application code) you must include an acknowledgement:
 *    "This product includes software written by Tim Hudson ([EMAIL PROTECTED])"
 * 
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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.
 * 
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.]
 */

/* The PPKI stuff has been donated by Jeff Barber <[EMAIL PROTECTED]> */

/* The SPKAC stuff has been donated by Massimiliano Pala <[EMAIL PROTECTED]> */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "apps.h"
#include <openssl/conf.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/txt_db.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/objects.h>
#include <openssl/pem.h>

#ifndef W_OK
#  ifdef VMS
#    if defined(__DECC)
#      include <unistd.h>
#    else
#      include <unixlib.h>
#    endif
#  else
#    include <sys/file.h>
#  endif
#endif

#ifndef W_OK
#  define F_OK 0
#  define X_OK 1
#  define W_OK 2
#  define R_OK 4
#endif

#undef PROG
#define PROG spkac_main

#define BASE_SECTION    "spkac"

static int fix_data(int nid, int *type);

static char *spkac_usage[]={
"usage: spkac args\n",
"\n",
" -in infile  - Input file [required]\n",
" -verbose    - Print a lot of info lines\n",
" -keysize    - Print SPKAC public key size\n",
" -verify     - Verify SPKAC public key signature\n",
" -noout      - Does not print hex value of public key\n",
"\n",
NULL
};

#ifdef EFENCE
extern int EF_PROTECT_FREE;
extern int EF_PROTECT_BELOW;
extern int EF_ALIGNMENT;
#endif

int MAIN(int argc, char **argv)
        {
        int total=0;
        int total_done=0;
        int badops=0;
        int ret=1;
        int verify=0;
        int noout=0;
        int verbose=0;
        int keysize=0;
        char *infile=NULL;
        char **pp;
        int i,j;
        long l;
        STACK_OF(CONF_VALUE) *attribs=NULL;
        STACK *cert_sk=NULL;
        BIO *STDout=NULL;
        STACK_OF(CONF_VALUE) *sk=NULL;
        LHASH *parms=NULL;
        CONF_VALUE *cv=NULL;
        NETSCAPE_SPKI *spki = NULL;
        unsigned char *spki_der = NULL,*p;
        char *type,*buf;
        EVP_PKEY *pktmp=NULL;
        int ok= -1;
        long errline;
        int nid;

#undef BSIZE
#define BSIZE 256

#ifdef EFENCE
EF_PROTECT_FREE=1;
EF_PROTECT_BELOW=1;
EF_ALIGNMENT=0;
#endif

        apps_startup();

        if (bio_err == NULL)
                if ((bio_err=BIO_new(BIO_s_file())) != NULL)
                        BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);

        STDout=BIO_new_fp(stdout,BIO_NOCLOSE);

        argc--;
        argv++;
        while (argc >= 1)
                {
                if      (strcmp(*argv,"-in") == 0)
                        {
                        if (--argc < 1) goto bad;
                        infile= *(++argv);
                        }
                else if (strcmp(*argv,"-keysize") == 0)
                        keysize=1;
                else if (strcmp(*argv,"-verbose") == 0)
                        verbose=1;
                else if (strcmp(*argv,"-noout") == 0)
                        noout=1;
                else if (strcmp(*argv,"-verify") == 0)
                        verify=1;
                else
                        {
bad:
                        BIO_printf(bio_err,"unknown option %s\n",*argv);
                        badops=1;
                        break;
                        }
                argc--;
                argv++;
                }
        if ( infile == NULL )
                badops=1;

        if (badops)
                {
                for (pp=spkac_usage; (*pp != NULL); pp++)
                        BIO_printf(bio_err,*pp);
                goto err;
                }

        ERR_load_crypto_strings();

        /*****************************************************************/

        if (infile != NULL)
        {
                parms=CONF_load(NULL,infile,&errline);
                if (parms == NULL)
                {
                        BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
                        ERR_print_errors(bio_err);
                        goto err;
                }

                sk=CONF_get_section(parms, "default");
                if (sk_CONF_VALUE_num(sk) == 0)
                {
                        BIO_printf(bio_err,"no name/value pairs found in %s\n",infile);
                        CONF_free(parms);
                        goto err;
                }

                for (i = 0; ; i++)
                {
                        if (sk_CONF_VALUE_num(sk) <= i) break;

                        cv=sk_CONF_VALUE_value(sk,i);
                        type=cv->name;
                        buf=cv->value;

                        if (verbose)
                                BIO_printf(STDout,"Parsing Line (%s)\n", type);

                        if ((nid=OBJ_txt2nid(type)) == NID_undef)
                        {
                                if (strcmp(type, "SPKAC") == 0)
                                {
                                        spki_der=(unsigned char *)Malloc(
                                                                strlen(cv->value)+1);
                                        if (spki_der == NULL)
                                        {
                                                BIO_printf(bio_err,"Malloc failure\n");
                                                goto err;
                                        }
                                        j = EVP_DecodeBlock(spki_der, (unsigned char 
*)cv->value,
                                                                strlen(cv->value));
                                        if (j <= 0)
                                        {
                                                BIO_printf(bio_err, "Can't b64 decode 
SPKAC struct\n");
                                                goto err;
                                        }

                                        p=spki_der;
                                        spki = d2i_NETSCAPE_SPKI(&spki, &p, j);
                                        Free(spki_der);
                                        spki_der = NULL;
                                        if (spki == NULL)
                                        {
                                                BIO_printf(bio_err,"Unable to load 
Netscape SPKAC\n");
                                                ERR_print_errors(bio_err);
                                                goto err;
                                        }
                                }
                        }

                        j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
                        if (fix_data(nid, &j) == 0)
                        {
                                BIO_printf(bio_err,
                                                "invalid characters in string 
%s\n",buf);
                                goto err;
                        }
                }

                if (spki == NULL)
                {
                        BIO_printf(bio_err,"Netscape SPKAC structure not found in 
%s\n",
                                infile);
                        goto err;
                }

                /*
                * Now extract the key from the SPKI structure.
                */

                if(verbose)
                        BIO_printf(STDout, "Unpacking SPKAC public key\n" );

                if ((pktmp=X509_PUBKEY_get(spki->spkac->pubkey)) == NULL)
                {
                        BIO_printf(bio_err,"error unpacking SPKAC public key\n");
                        goto err;
                }

                if(!noout)
                {
                        int y,z;
                        unsigned char *d;

                        z = EVP_PKEY_size(pktmp);
                        d=(unsigned char *) pktmp;

                        BIO_printf(STDout,"SPKAC Public Key = {\n");
                        for (y=0; y<z; y++)
                        {
                                BIO_printf(STDout,"0x%02X,",d[y]);
                                if ((y & 0x0f) == 0x0f)
                                        BIO_printf(STDout,"\n");
                         }
                         if (y%16 != 0) BIO_printf(STDout,"\n");
                         BIO_printf(STDout,"};\n");
                }

                if( keysize )
                {
                        int ks;
                        ks = EVP_PKEY_size(pktmp) * 8;
                        BIO_printf(STDout, "Key Size is %d\n", ks );
                }

                if( verify )
                {
                        if( verbose )
                                BIO_printf(STDout, "Checking the signature on SPKAC 
public key\n");

                        j = NETSCAPE_SPKI_verify(spki, pktmp);
                        if (j <= 0)
                        {
                                BIO_printf(bio_err,
                                        "Signature verification FAILED on SPKAC public 
key\n");
                                goto err;
                        }
                        BIO_printf(STDout, "Signature ok\n");
                }

        }
        /*****************************************************************/
        ret=0;
err:

        if (parms != NULL) CONF_free(parms);
        if (spki_der != NULL) Free(spki_der);
        if (spki != NULL) NETSCAPE_SPKI_free(spki);
        if (ret) ERR_print_errors(bio_err);
        BIO_free(STDout);
        EXIT(ret);

}


static int fix_data(int nid, int *type)
{
        if (nid == NID_pkcs9_emailAddress)
                *type=V_ASN1_IA5STRING;
        if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
                *type=V_ASN1_T61STRING;
        if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
                *type=V_ASN1_T61STRING;
        if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
                return(0);
        if (nid == NID_pkcs9_unstructuredName)
                *type=V_ASN1_IA5STRING;
        return(1);
}     

S/MIME Cryptographic Signature

Reply via email to