From 5409801c7195dc38665ec4e29c233bf1e9ea53e7 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Fri, 22 May 2009 17:56:11 -0400 Subject: Initial import of code. This is equivalent to the 20080124 tarball in the Fedora nss package tree. --- util.c | 288 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 util.c (limited to 'util.c') diff --git a/util.c b/util.c new file mode 100644 index 0000000..338b89d --- /dev/null +++ b/util.c @@ -0,0 +1,288 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Rob Crittenden (rcritten@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* cribbed from secutil.c */ + +#include "prtypes.h" +#include "prtime.h" +#include "prlong.h" +#include "prerror.h" +#include "prprf.h" +#include "plgetopt.h" +#include "prenv.h" +#include "prnetdb.h" +#include "base.h" +#include "base64.h" + +#include "cryptohi.h" +#include "secpkcs7.h" +#include "secerr.h" +#include + +#define CHUNK_SIZE 512 +#define PUT_Object(obj,err) \ + { \ + if (count >= size) { \ + *derlist = *derlist ? \ + nss_ZREALLOCARRAY(*derlist, SECItem *, \ + (size+CHUNK_SIZE) ) : \ + nss_ZNEWARRAY(NULL, SECItem *, \ + (size+CHUNK_SIZE) ) ; \ + if ((SECItem **)NULL == *derlist) { \ + err = CKR_HOST_MEMORY; \ + goto loser; \ + } \ + size += CHUNK_SIZE; \ + } \ + (*derlist)[ count ] = (obj); \ + count++; \ + } + +/* Read certificates from a flat file */ + +static SECItem *AllocItem(SECItem * item, unsigned int len) +{ + SECItem *result = NULL; + + if (item == NULL) { + result = nss_ZAlloc(NULL, sizeof(SECItem)); + if (result == NULL) { + goto loser; + } + } else { + PORT_Assert(item->data == NULL); + result = item; + } + + result->len = len; + if (len) { + result->data = nss_ZAlloc(NULL, len); + } + + return (result); + + loser: + if (result != NULL) { + SECITEM_FreeItem(result, (item == NULL) ? PR_TRUE : PR_FALSE); + } + return (NULL); +} + +static SECStatus FileToItem(SECItem * dst, PRFileDesc * src) +{ + PRFileInfo info; + PRInt32 numBytes; + PRStatus prStatus; + + prStatus = PR_GetOpenFileInfo(src, &info); + + if (prStatus != PR_SUCCESS) { + return SECFailure; + } + + /* XXX workaround for 3.1, not all utils zero dst before sending */ + dst->data = 0; + if (!AllocItem(dst, info.size+1)) + goto loser; + + numBytes = PR_Read(src, dst->data, info.size); + if (numBytes != info.size) { + goto loser; + } + + return SECSuccess; + loser: + SECITEM_FreeItem(dst, PR_FALSE); + nss_ZFreeIf(dst); + return SECFailure; +} + +int +ReadDERFromFile(SECItem *** derlist, char *filename, PRBool ascii, + int *cipher, char **ivstring, PRBool certsonly) +{ + SECStatus rv; + PRFileDesc *inFile; + int count = 0, size = 0; + SECItem *der; + int error; + SECItem filedata; + char *c, *iv; + + inFile = PR_Open(filename, PR_RDONLY, 0); + if (!inFile) + return -1; + + if (ascii) { + /* First convert ascii to binary */ + char *asc, *body; + + /* Read in ascii data */ + rv = FileToItem(&filedata, inFile); + asc = (char *) filedata.data; + if (!asc) { + PR_Close(inFile); + return -1; + } + + /* check for headers and trailers and remove them */ + if ((body = strstr(asc, "-----BEGIN")) != NULL) { + int key = 0; + while ((asc) && ((body = strstr(asc, "-----BEGIN")) != NULL)) { + key = 0; + if (strncmp(body, "-----BEGIN RSA PRIVATE KEY", 25) == 0) { + key = 1; + c = body; + body = strchr(body, '\n'); + body++; + if (strncmp(body, "Proc-Type: 4,ENCRYPTED", 22) == 0) { + body = strchr(body, '\n'); + body++; + if (strncmp(body, "DEK-Info: ", 10) == 0) { + body += 10; + c = body; + body = strchr(body, ','); + if (body == NULL) + goto loser; + *body = '\0'; + if (!strcasecmp(c, "DES-EDE3-CBC")) + *cipher = NSS_DES_EDE3_CBC; + else if (!strcasecmp(c, "DES-CBC")) + *cipher = NSS_DES_CBC; + else { + *cipher = -1; + goto loser; + } + body++; + iv = body; + body = strchr(body, '\n'); + if (body == NULL) + goto loser; + *body = '\0'; + body++; + *ivstring = strdup(iv); + } + } else { /* Else the private key is not encrypted */ + *cipher = 0; + body = c; + } + } + der = (SECItem *) malloc(sizeof(SECItem)); + + char *trailer = NULL; + asc = body; + body = strchr(body, '\n'); + if (!body) + body = strchr(asc, '\r'); /* maybe this is a MAC file */ + if (body) { + trailer = strstr(++body, "-----END"); + } + if (trailer != NULL) { + asc = trailer + 1; + *trailer = '\0'; + } else { + goto loser; + } + + /* Convert to binary */ + rv = ATOB_ConvertAsciiToItem(der, body); + if (rv) { + goto loser; + } + if ((certsonly && !key) || (!certsonly && key)) + PUT_Object(der, error); + } /* while */ + } else { /* No headers and footers, translate the blob */ + der = nss_ZNEW(NULL, SECItem); + rv = ATOB_ConvertAsciiToItem(der, asc); + if (rv) { + goto loser; + } + } + + nss_ZFreeIf(filedata.data); + filedata.data = 0; + filedata.len = 0; + } else { + /* Read in binary der */ + rv = FileToItem(der, inFile); + if (rv) { + PR_Close(inFile); + return -1; + } + } + PR_Close(inFile); + return count; + + loser: + if (filedata.len > 0) + nss_ZFreeIf(filedata.data); + PR_Close(inFile); + return -1; +} + +FILE *plogfile; + +void open_log() +{ +#ifdef DEBUG + plogfile = fopen("/tmp/pkcs11.log", "a"); +#endif + + return; +} + +void close_log() +{ +#ifdef DEBUG + fclose(plogfile); +#endif + return; +} + +void plog(const char *fmt, ...) +{ +#ifdef DEBUG + va_list ap; + + va_start(ap, fmt); + vfprintf(plogfile, fmt, ap); + va_end(ap); + + fflush(plogfile); +#endif +} -- cgit