summaryrefslogtreecommitdiff
path: root/release/src/router/matrixssl/src/pki
diff options
context:
space:
mode:
Diffstat (limited to 'release/src/router/matrixssl/src/pki')
-rw-r--r--release/src/router/matrixssl/src/pki/asn1.c454
-rw-r--r--release/src/router/matrixssl/src/pki/matrixPki.h138
-rw-r--r--release/src/router/matrixssl/src/pki/pkiInternal.h240
-rw-r--r--release/src/router/matrixssl/src/pki/rsaPki.c682
-rw-r--r--release/src/router/matrixssl/src/pki/x509.c1699
5 files changed, 0 insertions, 3213 deletions
diff --git a/release/src/router/matrixssl/src/pki/asn1.c b/release/src/router/matrixssl/src/pki/asn1.c
deleted file mode 100644
index 253e910b..00000000
--- a/release/src/router/matrixssl/src/pki/asn1.c
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * asn1.c
- * Release $Name: MATRIXSSL_1_8_8_OPEN $
- *
- * DER/BER coding
- */
-/*
- * Copyright (c) PeerSec Networks, 2002-2009. All Rights Reserved.
- * The latest version of this code is available at http://www.matrixssl.org
- *
- * This software is open source; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This General Public License does NOT permit incorporating this software
- * into proprietary programs. If you are unable to comply with the GPL, a
- * commercial license for this software may be purchased from PeerSec Networks
- * at http://www.peersec.com
- *
- * This program is distributed in WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * http://www.gnu.org/copyleft/gpl.html
- */
-/******************************************************************************/
-
-#include "pkiInternal.h"
-
-/******************************************************************************/
-/*
- On success, p will be updated to point to first character of value and
- valLen will contain number of bytes in value
- Return:
- 0 Success
- < 0 Error
-*/
-int32 asnParseLength(unsigned char **p, int32 size, int32 *valLen)
-{
- unsigned char *c, *end;
- int32 len, olen;
-
- c = *p;
- end = c + size;
- if (end - c < 1) {
- return -1;
- }
-/*
- If the length byte has high bit only set, it's an indefinite length
- We don't support this!
-*/
- if (*c == 0x80) {
- *valLen = -1;
- matrixStrDebugMsg("Unsupported: ASN indefinite length\n", NULL);
- return -1;
- }
-/*
- If the high bit is set, the lower 7 bits represent the number of
- bytes that follow and represent length
- If the high bit is not set, the lower 7 represent the actual length
-*/
- len = *c & 0x7F;
- if (*(c++) & 0x80) {
-/*
- Make sure there aren't more than 4 bytes of length specifier,
- and that we have that many bytes left in the buffer
-*/
- if (len > sizeof(int32) || len == 0x7f || (end - c) < len) {
- return -1;
- }
- olen = 0;
- while (len-- > 0) {
- olen = (olen << 8) | *c;
- c++;
- }
- if (olen < 0 || olen > INT_MAX) {
- return -1;
- }
- len = olen;
- }
- *p = c;
- *valLen = len;
- return 0;
-}
-
-/******************************************************************************/
-/*
- Callback to extract a big int32 (stream of bytes) from the DER stream
-*/
-int32 getBig(psPool_t *pool, unsigned char **pp, int32 len, mp_int *big)
-{
- unsigned char *p = *pp;
- int32 vlen;
-
- if (len < 1 || *(p++) != ASN_INTEGER ||
- asnParseLength(&p, len - 1, &vlen) < 0 || (len -1) < vlen) {
- matrixStrDebugMsg("ASN getBig failed\n", NULL);
- return -1;
- }
- mp_init(pool, big);
- if (mp_read_unsigned_bin(big, p, vlen) != 0) {
- mp_clear(big);
- matrixStrDebugMsg("ASN getBig failed\n", NULL);
- return -1;
- }
- p += vlen;
- *pp = p;
- return 0;
-}
-
-/******************************************************************************/
-/*
- Although a certificate serial number is encoded as an integer type, that
- doesn't prevent it from being abused as containing a variable length
- binary value. Get it here.
-*/
-int32 getSerialNum(psPool_t *pool, unsigned char **pp, int32 len,
- unsigned char **sn, int32 *snLen)
-{
- unsigned char *p = *pp;
- int32 vlen;
-
- if ((*p != (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2)) &&
- (*p != ASN_INTEGER)) {
- matrixStrDebugMsg("ASN getSerialNumber failed\n", NULL);
- return -1;
- }
- p++;
-
- if (len < 1 || asnParseLength(&p, len - 1, &vlen) < 0 || (len - 1) < vlen) {
- matrixStrDebugMsg("ASN getSerialNumber failed\n", NULL);
- return -1;
- }
- *snLen = vlen;
- *sn = psMalloc(pool, vlen);
- if (*sn == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memcpy(*sn, p, vlen);
- p += vlen;
- *pp = p;
- return 0;
-}
-
-/******************************************************************************/
-/*
- Callback to extract a sequence length from the DER stream
- Verifies that 'len' bytes are >= 'seqlen'
- Move pp to the first character in the sequence
-*/
-int32 getSequence(unsigned char **pp, int32 len, int32 *seqlen)
-{
- unsigned char *p = *pp;
-
- if (len < 1 || *(p++) != (ASN_SEQUENCE | ASN_CONSTRUCTED) ||
- asnParseLength(&p, len - 1, seqlen) < 0 || len < *seqlen) {
- return -1;
- }
- *pp = p;
- return 0;
-}
-
-/******************************************************************************/
-/*
- Extract a set length from the DER stream
-*/
-int32 getSet(unsigned char **pp, int32 len, int32 *setlen)
-{
- unsigned char *p = *pp;
-
- if (len < 1 || *(p++) != (ASN_SET | ASN_CONSTRUCTED) ||
- asnParseLength(&p, len - 1, setlen) < 0 || len < *setlen) {
- return -1;
- }
- *pp = p;
- return 0;
-}
-
-/******************************************************************************/
-/*
- Explicit value encoding has an additional tag layer
-*/
-int32 getExplicitVersion(unsigned char **pp, int32 len, int32 expVal, int32 *val)
-{
- unsigned char *p = *pp;
- int32 exLen;
-
- if (len < 1) {
- return -1;
- }
-/*
- This is an optional value, so don't error if not present. The default
- value is version 1
-*/
- if (*p != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | expVal)) {
- *val = 0;
- return 0;
- }
- p++;
- if (asnParseLength(&p, len - 1, &exLen) < 0 || (len - 1) < exLen) {
- return -1;
- }
- if (getInteger(&p, exLen, val) < 0) {
- return -1;
- }
- *pp = p;
- return 0;
-}
-
-/******************************************************************************/
-/*
- Implementation specific OID parser for suppported RSA algorithms
-*/
-int32 getAlgorithmIdentifier(unsigned char **pp, int32 len, int32 *oi,
- int32 isPubKey)
-{
- unsigned char *p = *pp, *end;
- int32 arcLen, llen;
-
- end = p + len;
- if (len < 1 || getSequence(&p, len, &llen) < 0) {
- return -1;
- }
- if (end - p < 1) {
- return -1;
- }
- if (*(p++) != ASN_OID || asnParseLength(&p, (int32)(end - p), &arcLen) < 0 ||
- llen < arcLen) {
- return -1;
- }
-/*
- List of expected (currently supported) OIDs - RFC 3279
- algorithm summed length hex
- sha1 88 05 2b0e03021a
- md2 646 08 2a864886f70d0202
- md5 649 08 2a864886f70d0205
-
- rsaEncryption 645 09 2a864886f70d010101
- md2WithRSAEncryption: 646 09 2a864886f70d010102
- md5WithRSAEncryption 648 09 2a864886f70d010104
- sha-1WithRSAEncryption 649 09 2a864886f70d010105
-
- Yes, the summing isn't ideal (as can be seen with the duplicate 649),
- but the specific implementation makes this ok.
-*/
- if (end - p < 2) {
- return -1;
- }
- if (isPubKey && (*p != 0x2a) && (*(p + 1) != 0x86)) {
-/*
- Expecting DSA here if not RSA, but OID doesn't always match
-*/
- matrixStrDebugMsg("Unsupported algorithm identifier\n", NULL);
- return -1;
- }
- *oi = 0;
- while (arcLen-- > 0) {
- *oi += (int32)*p++;
- }
-/*
- Each of these cases might have a trailing NULL parameter. Skip it
-*/
- if (*p != ASN_NULL) {
- *pp = p;
- return 0;
- }
- if (end - p < 2) {
- return -1;
- }
- *pp = p + 2;
- return 0;
-}
-
-/******************************************************************************/
-/*
- Implementation specific date parser.
- Does not actually verify the date
-*/
-int32 getValidity(psPool_t *pool, unsigned char **pp, int32 len,
- char **notBefore, char **notAfter)
-{
- unsigned char *p = *pp, *end;
- int32 seqLen, timeLen;
-
- end = p + len;
- if (len < 1 || *(p++) != (ASN_SEQUENCE | ASN_CONSTRUCTED) ||
- asnParseLength(&p, len - 1, &seqLen) < 0 || (end - p) < seqLen) {
- return -1;
- }
-/*
- Have notBefore and notAfter times in UTCTime or GeneralizedTime formats
-*/
- if ((end - p) < 1 || ((*p != ASN_UTCTIME) && (*p != ASN_GENERALIZEDTIME))) {
- return -1;
- }
- p++;
-/*
- Allocate them as null terminated strings
-*/
- if (asnParseLength(&p, seqLen, &timeLen) < 0 || (end - p) < timeLen) {
- return -1;
- }
- *notBefore = psMalloc(pool, timeLen + 1);
- if (*notBefore == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memcpy(*notBefore, p, timeLen);
- (*notBefore)[timeLen] = '\0';
- p = p + timeLen;
- if ((end - p) < 1 || ((*p != ASN_UTCTIME) && (*p != ASN_GENERALIZEDTIME))) {
- return -1;
- }
- p++;
- if (asnParseLength(&p, seqLen - timeLen, &timeLen) < 0 ||
- (end - p) < timeLen) {
- return -1;
- }
- *notAfter = psMalloc(pool, timeLen + 1);
- if (*notAfter == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memcpy(*notAfter, p, timeLen);
- (*notAfter)[timeLen] = '\0';
- p = p + timeLen;
-
- *pp = p;
- return 0;
-}
-
-/******************************************************************************/
-/*
- Currently just returning the raw BIT STRING and size in bytes
-*/
-int32 getSignature(psPool_t *pool, unsigned char **pp, int32 len,
- unsigned char **sig, int32 *sigLen)
-{
- unsigned char *p = *pp, *end;
- int32 ignore_bits, llen;
-
- end = p + len;
- if (len < 1 || (*(p++) != ASN_BIT_STRING) ||
- asnParseLength(&p, len - 1, &llen) < 0 || (end - p) < llen) {
- return -1;
- }
- ignore_bits = *p++;
-/*
- We assume this is always 0.
-*/
- sslAssert(ignore_bits == 0);
-/*
- Length included the ignore_bits byte
-*/
- *sigLen = llen - 1;
- *sig = psMalloc(pool, *sigLen);
- if (*sig == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memcpy(*sig, p, *sigLen);
- *pp = p + *sigLen;
- return 0;
-}
-
-/******************************************************************************/
-/*
- Could be optional. If the tag doesn't contain the value from the left
- of the IMPLICIT keyword we don't have a match and we don't incr the pointer.
-*/
-int32 getImplicitBitString(psPool_t *pool, unsigned char **pp, int32 len,
- int32 impVal, unsigned char **bitString, int32 *bitLen)
-{
- unsigned char *p = *pp;
- int32 ignore_bits;
-
- if (len < 1) {
- return -1;
- }
-/*
- We don't treat this case as an error, because of the optional nature.
-*/
- if (*p != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | impVal)) {
- return 0;
- }
-
- p++;
- if (asnParseLength(&p, len, bitLen) < 0) {
- return -1;
- }
- ignore_bits = *p++;
- sslAssert(ignore_bits == 0);
-
- *bitString = psMalloc(pool, *bitLen);
- if (*bitString == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memcpy(*bitString, p, *bitLen);
- *pp = p + *bitLen;
- return 0;
-}
-
-/******************************************************************************/
-/*
- Get an integer
-*/
-int32 getInteger(unsigned char **pp, int32 len, int32 *val)
-{
- unsigned char *p = *pp, *end;
- uint32 ui;
- int32 vlen;
-
- end = p + len;
- if (len < 1 || *(p++) != ASN_INTEGER ||
- asnParseLength(&p, len - 1, &vlen) < 0) {
- matrixStrDebugMsg("ASN getInteger failed\n", NULL);
- return -1;
- }
-/*
- This check prevents us from having a big positive integer where the
- high bit is set because it will be encoded as 5 bytes (with leading
- blank byte). If that is required, a getUnsigned routine should be used
-*/
- if (vlen > sizeof(int32) || end - p < vlen) {
- matrixStrDebugMsg("ASN getInteger failed\n", NULL);
- return -1;
- }
- ui = 0;
-/*
- If high bit is set, it's a negative integer, so perform the two's compliment
- Otherwise do a standard big endian read (most likely case for RSA)
-*/
- if (*p & 0x80) {
- while (vlen-- > 0) {
- ui = (ui << 8) | (*p ^ 0xFF);
- p++;
- }
- vlen = (int32)ui;
- vlen++;
- vlen = -vlen;
- *val = vlen;
- } else {
- while (vlen-- > 0) {
- ui = (ui << 8) | *p;
- p++;
- }
- *val = (int32)ui;
- }
- *pp = p;
- return 0;
-}
-
-/******************************************************************************/
diff --git a/release/src/router/matrixssl/src/pki/matrixPki.h b/release/src/router/matrixssl/src/pki/matrixPki.h
deleted file mode 100644
index aea0f1d5..00000000
--- a/release/src/router/matrixssl/src/pki/matrixPki.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * matrixPki.h
- * Release $Name: MATRIXSSL_1_8_8_OPEN $
- *
- * Public header file for MatrixPKI extension
- * Implementations interacting with the PKI portion of the
- * matrixssl library should only use the APIs and definitions
- * used in this file.
- */
-/*
- * Copyright (c) PeerSec Networks, 2002-2009. All Rights Reserved.
- * The latest version of this code is available at http://www.matrixssl.org
- *
- * This software is open source; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This General Public License does NOT permit incorporating this software
- * into proprietary programs. If you are unable to comply with the GPL, a
- * commercial license for this software may be purchased from PeerSec Networks
- * at http://www.peersec.com
- *
- * This program is distributed in WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * http://www.gnu.org/copyleft/gpl.html
- */
-/******************************************************************************/
-
-#ifndef _h_MATRIXPKI
-#define _h_MATRIXPKI
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- Because the set of APIs exposed here is dependent on the package, the
- crypto layer header must be parsed to determine what defines are configured
- (USE_RSA, and USE_X509 specifically)
-*/
-#include "../../matrixCommon.h"
-#include "../crypto/matrixCrypto.h"
-
-#define REQ_FILE_TYPE 0
-#define KEY_FILE_TYPE 1
-#define CERT_FILE_TYPE 2
-
-#define MAX_CHAIN_LENGTH 16
-typedef uint32 sslChainLen_t[MAX_CHAIN_LENGTH];
-/******************************************************************************/
-/*
- * PKI documented APIs
- */
-MATRIXPUBLIC int32 matrixPkiOpen(void);
-MATRIXPUBLIC void matrixPkiClose(void);
-
-#ifdef USE_RSA
-/*
- Private key reading and conversions
-*/
-#ifdef USE_FILE_SYSTEM
-MATRIXPUBLIC int32 matrixX509ReadPrivKey(psPool_t *pool, const char *fileName,
- const char *password, unsigned char **out,
- int32 *outLen);
-#endif /* USE_FILE_SYSTEM */
-MATRIXPUBLIC int32 matrixRsaParsePrivKey(psPool_t *pool, unsigned char *keyBuf,
- int32 keyBufLen, sslRsaKey_t **key);
-MATRIXPUBLIC int32 matrixRsaParsePubKey(psPool_t *pool, unsigned char *keyBuf,
- int32 keyBufLen, sslRsaKey_t **key);
-MATRIXPUBLIC void matrixRsaFreeKey(sslRsaKey_t *key);
-MATRIXPUBLIC int32 matrixRsaConvertToPublicKey(psPool_t *pool,
- sslRsaKey_t *privKey, sslRsaKey_t **pubKey);
-
-/*
- USE_X509 adds certificate support
-*/
-#ifdef USE_X509
-MATRIXPUBLIC int32 matrixX509ReadKeysMem(sslKeys_t **keys,
- unsigned char *certBuf, int32 certLen,
- unsigned char *privBuf, int32 privLen,
- unsigned char *trustedCABuf, int32 trustedCALen);
-MATRIXPUBLIC void matrixRsaFreeKeys(sslKeys_t *keys);
-
-#ifdef USE_FILE_SYSTEM
-MATRIXPUBLIC int32 matrixX509ReadKeys(sslKeys_t **keys, const char *certFile,
- const char *privFile, const char *privPass,
- const char *trustedCAFile);
-MATRIXPUBLIC int32 matrixX509ReadKeysEx(psPool_t *pool, sslKeys_t **keys,
- const char *certFile, const char *privFile,
- const char *privPass, const char *trustedCAFiles);
-MATRIXPUBLIC int32 matrixX509ReadCert(psPool_t *pool, const char *fileName,
- unsigned char **out, int32 *outLen,
- sslChainLen_t *chain);
-MATRIXPUBLIC int32 matrixX509ReadPubKey(psPool_t *pool, const char *certFile,
- sslRsaKey_t **key);
-#endif /* USE_FILE_SYSTEM */
-
-MATRIXPUBLIC int32 matrixRsaParseKeysMem(psPool_t *pool, sslKeys_t **keys,
- unsigned char *certBuf, int32 certLen, unsigned char *privBuf,
- int32 privLen, unsigned char *trustedCABuf, int32 trustedCALen);
-MATRIXPUBLIC int32 matrixX509ParseCert(psPool_t *pool, unsigned char *certBuf,
- int32 certlen, sslCert_t **cert);
-MATRIXPUBLIC void matrixX509FreeCert(sslCert_t *cert);
-MATRIXPUBLIC int32 matrixX509ParsePubKey(psPool_t *pool, unsigned char *certBuf,
- int32 certLen, sslRsaKey_t **key);
-MATRIXPUBLIC int32 matrixX509ValidateCert(psPool_t *pool,
- sslCert_t *subjectCert, sslCert_t *issuerCert,
- int32 *valid);
-MATRIXPUBLIC int32 matrixX509ValidateCertChain(psPool_t *pool,
- sslCert_t *chain, sslCert_t **subjectCert,
- int32 *valid);
-MATRIXPUBLIC int32 matrixX509UserValidator(psPool_t *pool,
- sslCert_t *subjectCert,
- int32 (*certValidator)(sslCertInfo_t *t, void *arg),
- void *arg);
-#endif /* USE_X509 */
-
-
-
-#endif /* USE_RSA */
-
-
-/******************************************************************************/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _h_MATRIXPKI */
-
-/******************************************************************************/
-
diff --git a/release/src/router/matrixssl/src/pki/pkiInternal.h b/release/src/router/matrixssl/src/pki/pkiInternal.h
deleted file mode 100644
index ef89feb3..00000000
--- a/release/src/router/matrixssl/src/pki/pkiInternal.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * pkiInternal.h
- * Release $Name: MATRIXSSL_1_8_8_OPEN $
- *
- * Public header file for MatrixSSL PKI extension
- * Implementations interacting with the PKI portion of the
- * matrixssl library should only use the APIs and definitions
- * used in this file.
- */
-/*
- * Copyright (c) PeerSec Networks, 2002-2009. All Rights Reserved.
- * The latest version of this code is available at http://www.matrixssl.org
- *
- * This software is open source; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This General Public License does NOT permit incorporating this software
- * into proprietary programs. If you are unable to comply with the GPL, a
- * commercial license for this software may be purchased from PeerSec Networks
- * at http://www.peersec.com
- *
- * This program is distributed in WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * http://www.gnu.org/copyleft/gpl.html
- */
-/******************************************************************************/
-
-#ifndef _h_PSPKI_INTERNAL
-#define _h_PSPKI_INTERNAL
-#define _h_EXPORT_SYMBOLS
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- Require OS for PeerSec malloc and crypto to determine what we include here
-*/
-#include "../../matrixCommon.h"
-#include "../os/osLayer.h"
-#include "../crypto/cryptoLayer.h"
-
-/******************************************************************************/
-/*
- ASN defines
-
- 8 bit bit masks for ASN.1 tag field
-*/
-#define ASN_PRIMITIVE 0x0
-#define ASN_CONSTRUCTED 0x20
-
-#define ASN_UNIVERSAL 0x0
-#define ASN_APPLICATION 0x40
-#define ASN_CONTEXT_SPECIFIC 0x80
-#define ASN_PRIVATE 0xC0
-
-/*
- ASN.1 primitive data types
-*/
-enum {
- ASN_BOOLEAN = 1,
- ASN_INTEGER,
- ASN_BIT_STRING,
- ASN_OCTET_STRING,
- ASN_NULL,
- ASN_OID,
- ASN_UTF8STRING = 12,
- ASN_SEQUENCE = 16,
- ASN_SET,
- ASN_PRINTABLESTRING = 19,
- ASN_T61STRING,
- ASN_IA5STRING = 22,
- ASN_UTCTIME,
- ASN_GENERALIZEDTIME,
- ASN_GENERAL_STRING = 27,
- ASN_BMPSTRING = 30
-};
-
-
-extern int32 getBig(psPool_t *pool, unsigned char **pp, int32 len, mp_int *big);
-extern int32 getSerialNum(psPool_t *pool, unsigned char **pp, int32 len,
- unsigned char **sn, int32 *snLen);
-extern int32 getInteger(unsigned char **pp, int32 len, int32 *val);
-extern int32 getSequence(unsigned char **pp, int32 len, int32 *outLen);
-extern int32 getSet(unsigned char **pp, int32 len, int32 *outLen);
-extern int32 getExplicitVersion(unsigned char **pp, int32 len, int32 expVal,
- int32 *outLen);
-extern int32 getAlgorithmIdentifier(unsigned char **pp, int32 len, int32 *oi,
- int32 isPubKey);
-extern int32 getValidity(psPool_t *pool, unsigned char **pp, int32 len,
- char **notBefore, char **notAfter);
-extern int32 getSignature(psPool_t *pool, unsigned char **pp, int32 len,
- unsigned char **sig, int32 *sigLen);
-extern int32 getImplicitBitString(psPool_t *pool, unsigned char **pp, int32 len,
- int32 impVal, unsigned char **bitString, int32 *bitLen);
-
-/*
- Define to enable more extension parsing
-*/
-#define USE_FULL_CERT_PARSE
-
-/******************************************************************************/
-/*
- The USE_RSA define is primarily for future compat when more key exchange
- protocols are added. Crypto should always define this for now.
-*/
-#define OID_RSA_MD2 646
-#define OID_RSA_MD5 648
-#define OID_RSA_SHA1 649
-
-/*
- DN attributes are used outside the X509 area for cert requests,
- which have been included in the RSA portions of the code
-*/
-typedef struct {
- char *country;
- char *state;
- char *locality;
- char *organization;
- char *orgUnit;
- char *commonName;
- char hash[SSL_SHA1_HASH_SIZE];
-} DNattributes_t;
-
-
-#ifdef USE_X509
-
-typedef struct {
- int32 ca;
- int32 pathLenConstraint;
-} extBasicConstraints_t;
-
-typedef struct {
- int32 len;
- unsigned char *id;
-} extSubjectKeyId_t;
-
-typedef struct {
- int32 keyLen;
- unsigned char *keyId;
- DNattributes_t attribs;
- int32 serialNumLen;
- unsigned char *serialNum;
-} extAuthKeyId_t;
-/*
- FUTURE: add support for the other extensions
-*/
-typedef struct {
- extBasicConstraints_t bc;
- sslSubjectAltName_t *san;
-#ifdef USE_FULL_CERT_PARSE
- extSubjectKeyId_t sk;
- extAuthKeyId_t ak;
- unsigned char *keyUsage;
- int32 keyUsageLen;
-#endif /* USE_FULL_CERT_PARSE */
-} v3extensions_t;
-
-typedef struct sslCert {
- int32 version;
- int32 valid;
- unsigned char *serialNumber;
- int32 serialNumberLen;
- DNattributes_t issuer;
- DNattributes_t subject;
- char *notBefore;
- char *notAfter;
- sslRsaKey_t publicKey;
- int32 certAlgorithm;
- int32 sigAlgorithm;
- int32 pubKeyAlgorithm;
- unsigned char *signature;
- int32 signatureLen;
- unsigned char sigHash[SSL_SHA1_HASH_SIZE];
- unsigned char *uniqueUserId;
- int32 uniqueUserIdLen;
- unsigned char *uniqueSubjectId;
- int32 uniqueSubjectIdLen;
- v3extensions_t extensions;
- struct sslCert *next;
-} sslCert_t;
-
-typedef struct sslLocalCert {
- sslRsaKey_t *privKey;
- unsigned char *certBin;
- uint32 certLen;
- struct sslLocalCert *next;
-} sslLocalCert_t;
-
-typedef struct {
- sslLocalCert_t cert;
-#ifdef USE_CLIENT_SIDE_SSL
- sslCert_t *caCerts;
-#endif /* USE_CLIENT_SIDE_SSL */
-} sslKeys_t;
-
-#endif /* USE_X509 */
-
-
-
-/*
- Helpers for inter-pki communications
-*/
-extern int32 asnParseLength(unsigned char **p, int32 size, int32 *valLen);
-extern int32 psAsnConfirmSignature(unsigned char *sigHash,
- unsigned char *sigOut, int32 sigLen);
-extern int32 getDNAttributes(psPool_t *pool, unsigned char **pp, int32 len,
- DNattributes_t *attribs);
-extern int32 getPubKey(psPool_t *pool, unsigned char **pp, int32 len,
- sslRsaKey_t *pubKey);
-extern void psFreeDNStruct(DNattributes_t *dn);
-
-#ifdef USE_FILE_SYSTEM
-extern int32 readCertChain(psPool_t *pool, const char *certFiles,
- sslLocalCert_t *lkeys);
-extern int32 psGetFileBin(psPool_t *pool, const char *fileName,
- unsigned char **bin, int32 *binLen);
-extern int32 base64encodeAndWrite(psPool_t *pool, const char *fileName,
- unsigned char *bin, int32 binLen, int32 fileType,
- char *hexCipherIV, int32 hexCipherIVLen);
-#endif /* USE_FILE_SYSTEM */
-
-/*
- Finally, include the public header
-*/
-#include "matrixPki.h"
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _h_PSPKI_INTERNAL */
-
diff --git a/release/src/router/matrixssl/src/pki/rsaPki.c b/release/src/router/matrixssl/src/pki/rsaPki.c
deleted file mode 100644
index 29a40b02..00000000
--- a/release/src/router/matrixssl/src/pki/rsaPki.c
+++ /dev/null
@@ -1,682 +0,0 @@
-/*
- * rsaPki.c
- * Release $Name: MATRIXSSL_1_8_8_OPEN $
- *
- * RSA key and cert reading
- */
-/*
- * Copyright (c) PeerSec Networks, 2002-2009. All Rights Reserved.
- * The latest version of this code is available at http://www.matrixssl.org
- *
- * This software is open source; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This General Public License does NOT permit incorporating this software
- * into proprietary programs. If you are unable to comply with the GPL, a
- * commercial license for this software may be purchased from PeerSec Networks
- * at http://www.peersec.com
- *
- * This program is distributed in WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifdef VXWORKS
-#include <vxWorks.h>
-#endif /* VXWORKS */
-
-#include "pkiInternal.h"
-
-#ifndef WINCE
-#ifdef USE_FILE_SYSTEM
- #include <sys/stat.h>
- #include <signal.h>
-#endif /* USE_FILE_SYSTEM */
-#endif /* WINCE */
-/*
- For our purposes USE_RSA is used to indicate RSA private key handling.
- USE_X509 indicates certificate handling and those blocks should be
- wrapped inside USE_RSA because that is the only key type currently supported
-*/
-#ifdef USE_RSA
-
-#define ATTRIB_COUNTRY_NAME 6
-#define ATTRIB_LOCALITY 7
-#define ATTRIB_ORGANIZATION 10
-#define ATTRIB_ORG_UNIT 11
-#define ATTRIB_DN_QUALIFIER 46
-#define ATTRIB_STATE_PROVINCE 8
-#define ATTRIB_COMMON_NAME 3
-
-
-#ifdef USE_3DES
-static const char encryptHeader[] = "DEK-Info: DES-EDE3-CBC,";
-static int32 hexToBinary(unsigned char *hex, unsigned char *bin, int32 binlen);
-#endif
-
-static int32 psAsnParsePrivateKey(psPool_t *pool, unsigned char **pp,
- int32 size, sslRsaKey_t *key);
-#endif /* USE_RSA */
-
-
-/******************************************************************************/
-/*
- Open and close the PKI module. These routines are called once in the
- lifetime of the application and initialize and clean up the library
- respectively.
-*/
-int32 matrixPkiOpen(void)
-{
- if (sslOpenOsdep() < 0) {
- matrixStrDebugMsg("Osdep open failure\n", NULL);
- return -1;
- }
- return 0;
-}
-
-void matrixPkiClose(void)
-{
- sslCloseOsdep();
-}
-#ifdef USE_FILE_SYSTEM
-/******************************************************************************/
-/*
- Return the file contents given a file name in a single allocated buffer.
- Not a good routine to use generally with the fixed mem stuff. Not
- actually doing a 'binary' file read. Only using the 'r' attribute since
- all the cert and key files are text.
-*/
-int32 psGetFileBin(psPool_t *pool, const char *fileName, unsigned char **bin,
- int32 *binLen)
-{
- FILE *fp;
- struct stat fstat;
- size_t tmp = 0;
-
- *binLen = 0;
- *bin = NULL;
-
- if (fileName == NULL) {
- return -1;
- }
- if ((stat(fileName, &fstat) != 0) || (fp = fopen(fileName, "r")) == NULL) {
- return -7; /* FILE_NOT_FOUND */
- }
-
- *bin = psMalloc(pool, fstat.st_size + 1);
- if (*bin == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memset(*bin, 0x0, fstat.st_size + 1);
- while (((tmp = fread(*bin + *binLen, sizeof(char), 512, fp)) > 0) &&
- (*binLen < fstat.st_size)) {
- *binLen += (int32)tmp;
- }
- fclose(fp);
- return 0;
-}
-
-/******************************************************************************/
-/*
- * Public API to return an ASN.1 encoded key stream from a PEM private
- * key file
- *
- * If password is provided, we only deal with 3des cbc encryption
- * Function allocates key on success. User must free.
- */
-int32 matrixX509ReadPrivKey(psPool_t *pool, const char *fileName,
- const char *password, unsigned char **keyMem, int32 *keyMemLen)
-{
- unsigned char *keyBuf, *DERout;
- char *start, *end, *endTmp;
- int32 keyBufLen, rc, DERlen, PEMlen = 0;
-#ifdef USE_3DES
- sslCipherContext_t ctx;
- unsigned char passKey[SSL_DES3_KEY_LEN];
- unsigned char cipherIV[SSL_DES3_IV_LEN];
- int32 tmp, encrypted = 0;
-#endif /* USE_3DES */
-
- if (fileName == NULL) {
- return 0;
- }
- *keyMem = NULL;
- if ((rc = psGetFileBin(pool, fileName, &keyBuf, &keyBufLen)) < 0) {
- return rc;
- }
- start = end = NULL;
-
-/*
- * Check header and encryption parameters.
- */
- if (((start = strstr((char*)keyBuf, "-----BEGIN")) != NULL) &&
- ((start = strstr((char*)keyBuf, "PRIVATE KEY-----")) != NULL) &&
- ((end = strstr(start, "-----END")) != NULL) &&
- ((endTmp = strstr(end, "PRIVATE KEY-----")) != NULL)) {
- start += strlen("PRIVATE KEY-----");
- while (*start == '\r' || *start == '\n') {
- start++;
- }
- PEMlen = (int32)(end - start);
- } else {
- matrixStrDebugMsg("Error parsing private key buffer\n", NULL);
- psFree(keyBuf);
- return -1;
- }
-
- if (strstr((char*)keyBuf, "Proc-Type:") &&
- strstr((char*)keyBuf, "4,ENCRYPTED")) {
-#ifdef USE_3DES
- encrypted++;
- if (password == NULL) {
- matrixStrDebugMsg("No password given for encrypted private key\n",
- NULL);
- psFree(keyBuf);
- return -1;
- }
- if ((start = strstr((char*)keyBuf, encryptHeader)) == NULL) {
- matrixStrDebugMsg("Unrecognized private key file encoding\n",
- NULL);
- psFree(keyBuf);
- return -1;
- }
- start += strlen(encryptHeader);
- /* SECURITY - we assume here that header points to at least 16 bytes of data */
- tmp = hexToBinary((unsigned char*)start, cipherIV, SSL_DES3_IV_LEN);
- if (tmp < 0) {
- matrixStrDebugMsg("Invalid private key file salt\n", NULL);
- psFree(keyBuf);
- return -1;
- }
- start += tmp;
- generate3DESKey((unsigned char*)password, (int32)strlen(password),
- cipherIV, (unsigned char*)passKey);
- PEMlen = (int32)(end - start);
-#else /* !USE_3DES */
-/*
- * The private key is encrypted, but 3DES support has been turned off
- */
- matrixStrDebugMsg("3DES has been disabled for private key decrypt\n", NULL);
- psFree(keyBuf);
- return -1;
-#endif /* USE_3DES */
- }
-
-/*
- Take the raw input and do a base64 decode
- */
- DERout = psMalloc(pool, PEMlen);
- if (DERout == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- DERlen = PEMlen;
- if (ps_base64_decode((unsigned char*)start, PEMlen, DERout,
- (uint32*)&DERlen) != 0) {
- psFree(DERout);
- psFree(keyBuf);
- matrixStrDebugMsg("Unable to base64 decode private key\n", NULL);
- return -1;
- }
- psFree(keyBuf);
-#ifdef USE_3DES
-/*
- * Decode
- */
- if (encrypted == 1 && password) {
- matrix3desInit(&ctx, cipherIV, passKey, SSL_DES3_KEY_LEN);
- matrix3desDecrypt(&ctx, DERout, DERout, DERlen);
- }
-#endif /* USE_3DES */
-/*
- Don't parse this here. Return the ASN.1 encoded buf to be
- consistent with the other mem APIs. Use the ParsePrivKey
- function if you want the structure format
-*/
- *keyMem = DERout;
- *keyMemLen = DERlen;
- return rc;
-}
-
-#ifdef USE_3DES
-/******************************************************************************/
-/*
- Convert an ASCII hex representation to a binary buffer.
- Decode enough data out of 'hex' buffer to produce 'binlen' bytes in 'bin'
- Two digits of ASCII hex map to the high and low nybbles (in that order),
- so this function assumes that 'hex' points to 2x 'binlen' bytes of data.
- Return the number of bytes processed from hex (2x binlen) or < 0 on error.
-*/
-static int32 hexToBinary(unsigned char *hex, unsigned char *bin, int32 binlen)
-{
- unsigned char *end, c, highOrder;
-
- highOrder = 1;
- for (end = hex + binlen * 2; hex < end; hex++) {
- c = *hex;
- if ('0' <= c && c <='9') {
- c -= '0';
- } else if ('a' <= c && c <='f') {
- c -= ('a' - 10);
- } else if ('A' <= c && c <='F') {
- c -= ('A' - 10);
- } else {
- return -1;
- }
- if (highOrder++ & 0x1) {
- *bin = c << 4;
- } else {
- *bin |= c;
- bin++;
- }
- }
- return binlen * 2;
-}
-#endif /* USE_3DES */
-#endif /* USE_FILE_SYSTEM */
-
-/******************************************************************************/
-/*
- * In memory version of matrixRsaReadPrivKey. The keyBuf is the raw
- * ASN.1 encoded buffer.
- */
-int32 matrixRsaParsePrivKey(psPool_t *pool, unsigned char *keyBuf,
- int32 keyBufLen, sslRsaKey_t **key)
-{
- unsigned char *asnp;
-
-/*
- Now have the DER stream to extract from in asnp
- */
- *key = psMalloc(pool, sizeof(sslRsaKey_t));
- if (*key == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memset(*key, 0x0, sizeof(sslRsaKey_t));
-
- asnp = keyBuf;
- if (psAsnParsePrivateKey(pool, &asnp, keyBufLen, *key) < 0) {
- matrixRsaFreeKey(*key);
- *key = NULL;
- matrixStrDebugMsg("Unable to ASN parse private key.\n", NULL);
- return -1;
- }
-
- return 0;
-}
-
-/******************************************************************************/
-/*
- Binary to struct helper for RSA public keys.
-*/
-int32 matrixRsaParsePubKey(psPool_t *pool, unsigned char *keyBuf,
- int32 keyBufLen, sslRsaKey_t **key)
-{
- unsigned char *p, *end;
- int32 len;
-
- p = keyBuf;
- end = p + keyBufLen;
-/*
- Supporting both the PKCS#1 RSAPublicKey format and the
- X.509 SubjectPublicKeyInfo format. If encoding doesn't start with
- the SEQUENCE identifier for the SubjectPublicKeyInfo format, jump down
- to the RSAPublicKey subset parser and try that
-*/
- if (getSequence(&p, (int32)(end - p), &len) == 0) {
- if (getAlgorithmIdentifier(&p, (int32)(end - p), &len, 1) < 0) {
- return -1;
- }
- }
-/*
- Now have the DER stream to extract from in asnp
- */
- *key = psMalloc(pool, sizeof(sslRsaKey_t));
- if (*key == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memset(*key, 0x0, sizeof(sslRsaKey_t));
- if (getPubKey(pool, &p, (int32)(end - p), *key) < 0) {
- matrixRsaFreeKey(*key);
- *key = NULL;
- matrixStrDebugMsg("Unable to ASN parse public key\n", NULL);
- return -1;
- }
- return 0;
-}
-
-/******************************************************************************/
-/*
- * Free an RSA key. mp_clear will zero the memory of each element and free it.
- */
-void matrixRsaFreeKey(sslRsaKey_t *key)
-{
- mp_clear(&(key->N));
- mp_clear(&(key->e));
- mp_clear(&(key->d));
- mp_clear(&(key->p));
- mp_clear(&(key->q));
- mp_clear(&(key->dP));
- mp_clear(&(key->dQ));
- mp_clear(&(key->qP));
- psFree(key);
-}
-
-/******************************************************************************/
-/*
- Parse a a private key structure in DER formatted ASN.1
- Per ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
- RSAPrivateKey ::= SEQUENCE {
- version Version,
- modulus INTEGER, -- n
- publicExponent INTEGER, -- e
- privateExponent INTEGER, -- d
- prime1 INTEGER, -- p
- prime2 INTEGER, -- q
- exponent1 INTEGER, -- d mod (p-1)
- exponent2 INTEGER, -- d mod (q-1)
- coefficient INTEGER, -- (inverse of q) mod p
- otherPrimeInfos OtherPrimeInfos OPTIONAL
- }
- Version ::= INTEGER { two-prime(0), multi(1) }
- (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
-
- Which should look something like this in hex (pipe character
- is used as a delimiter):
- ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc
- 30 Tag in binary: 00|1|10000 -> UNIVERSAL | CONSTRUCTED | SEQUENCE (16)
- 82 Length in binary: 1 | 0000010 -> LONG LENGTH | LENGTH BYTES (2)
- 04 A4 Length Bytes (1188)
- 02 Tag in binary: 00|0|00010 -> UNIVERSAL | PRIMITIVE | INTEGER (2)
- 01 Length in binary: 0|0000001 -> SHORT LENGTH | LENGTH (1)
- 00 INTEGER value (0) - RSAPrivateKey.version
- 02 Tag in binary: 00|0|00010 -> UNIVERSAL | PRIMITIVE | INTEGER (2)
- 82 Length in binary: 1 | 0000010 -> LONG LENGTH | LENGTH BYTES (2)
- 01 01 Length Bytes (257)
- [] 257 Bytes of data - RSAPrivateKey.modulus (2048 bit key)
- 02 Tag in binary: 00|0|00010 -> UNIVERSAL | PRIMITIVE | INTEGER (2)
- 03 Length in binary: 0|0000011 -> SHORT LENGTH | LENGTH (3)
- 01 00 01 INTEGER value (65537) - RSAPrivateKey.publicExponent
- ...
-
- OtherPrimeInfos is not supported in this routine, and an error will be
- returned if they are present
-*/
-
-static int32 psAsnParsePrivateKey(psPool_t *pool, unsigned char **pp,
- int32 size, sslRsaKey_t *key)
-{
- unsigned char *p, *end, *seq;
- int32 version, seqlen;
-
- key->optimized = 0;
- p = *pp;
- end = p + size;
-
- if (getSequence(&p, size, &seqlen) < 0) {
- matrixStrDebugMsg("ASN sequence parse error\n", NULL);
- return -1;
- }
- seq = p;
- if (getInteger(&p, (int32)(end - p), &version) < 0 || version != 0 ||
- getBig(pool, &p, (int32)(end - p), &(key->N)) < 0 ||
- mp_shrink(&key->N) != MP_OKAY ||
- getBig(pool, &p, (int32)(end - p), &(key->e)) < 0 ||
- mp_shrink(&key->e) != MP_OKAY ||
- getBig(pool, &p, (int32)(end - p), &(key->d)) < 0 ||
- mp_shrink(&key->d) != MP_OKAY ||
- getBig(pool, &p, (int32)(end - p), &(key->p)) < 0 ||
- mp_shrink(&key->p) != MP_OKAY ||
- getBig(pool, &p, (int32)(end - p), &(key->q)) < 0 ||
- mp_shrink(&key->q) != MP_OKAY ||
- getBig(pool, &p, (int32)(end - p), &(key->dP)) < 0 ||
- mp_shrink(&key->dP) != MP_OKAY ||
- getBig(pool, &p, (int32)(end - p), &(key->dQ)) < 0 ||
- mp_shrink(&key->dQ) != MP_OKAY ||
- getBig(pool, &p, (int32)(end - p), &(key->qP)) < 0 ||
- mp_shrink(&key->qP) != MP_OKAY ||
- (int32)(p - seq) != seqlen) {
- matrixStrDebugMsg("ASN key extract parse error\n", NULL);
- return -1;
- }
-/*
- If we made it here, the key is ready for optimized decryption
-*/
- key->optimized = 1;
-
- *pp = p;
-/*
- Set the key length of the key
-*/
- key->size = mp_unsigned_bin_size(&key->N);
- return 0;
-}
-
-
-/******************************************************************************/
-/*
- Implementations of this specification MUST be prepared to receive
- the following standard attribute types in issuer names:
- country, organization, organizational-unit, distinguished name qualifier,
- state or province name, and common name
-*/
-int32 getDNAttributes(psPool_t *pool, unsigned char **pp, int32 len,
- DNattributes_t *attribs)
-{
- sslSha1Context_t hash;
- unsigned char *p = *pp;
- unsigned char *dnEnd, *dnStart;
- int32 llen, setlen, arcLen, id, stringType;
- char *stringOut;
-
- dnStart = p;
- if (getSequence(&p, len, &llen) < 0) {
- return -1;
- }
- dnEnd = p + llen;
-
- matrixSha1Init(&hash);
- while (p < dnEnd) {
- if (getSet(&p, (int32)(dnEnd - p), &setlen) < 0) {
- return -1;
- }
- if (getSequence(&p, (int32)(dnEnd - p), &llen) < 0) {
- return -1;
- }
- if (dnEnd <= p || (*(p++) != ASN_OID) ||
- asnParseLength(&p, (int32)(dnEnd - p), &arcLen) < 0 ||
- (dnEnd - p) < arcLen) {
- return -1;
- }
-/*
- id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4}
- id-at-commonName OBJECT IDENTIFIER ::= {id-at 3}
- id-at-countryName OBJECT IDENTIFIER ::= {id-at 6}
- id-at-localityName OBJECT IDENTIFIER ::= {id-at 7}
- id-at-stateOrProvinceName OBJECT IDENTIFIER ::= {id-at 8}
- id-at-organizationName OBJECT IDENTIFIER ::= {id-at 10}
- id-at-organizationalUnitName OBJECT IDENTIFIER ::= {id-at 11}
-*/
- *pp = p;
-/*
- FUTURE: Currently skipping OIDs not of type {joint-iso-ccitt(2) ds(5) 4}
- However, we could be dealing with an OID we MUST support per RFC.
- domainComponent is one such example.
-*/
- if (dnEnd - p < 2) {
- return -1;
- }
- if ((*p++ != 85) || (*p++ != 4) ) {
- p = *pp;
-/*
- Move past the OID and string type, get data size, and skip it.
- NOTE: Have had problems parsing older certs in this area.
-*/
- if (dnEnd - p < arcLen + 1) {
- return -1;
- }
- p += arcLen + 1;
- if (asnParseLength(&p, (int32)(dnEnd - p), &llen) < 0 ||
- dnEnd - p < llen) {
- return -1;
- }
- p = p + llen;
- continue;
- }
-/*
- Next are the id of the attribute type and the ASN string type
-*/
- if (arcLen != 3 || dnEnd - p < 2) {
- return -1;
- }
- id = (int32)*p++;
-/*
- Done with OID parsing
-*/
- stringType = (int32)*p++;
-
- if (asnParseLength(&p, (int32)(dnEnd - p), &llen) < 0 ||
- dnEnd - p < llen) {
- return -1;
- }
- switch (stringType) {
- case ASN_PRINTABLESTRING:
- case ASN_UTF8STRING:
- case ASN_IA5STRING:
- case ASN_T61STRING:
- case ASN_BMPSTRING:
- stringOut = psMalloc(pool, llen + 1);
- if (stringOut == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memcpy(stringOut, p, llen);
- stringOut[llen] = '\0';
-/*
- Catch any hidden \0 chars in these members to address the
- issue of www.goodguy.com\0badguy.com
-*/
- if (strlen(stringOut) != llen) {
- psFree(stringOut);
- return -1;
- }
-
- p = p + llen;
- break;
- default:
- matrixStrDebugMsg("Parsing untested DN attrib type\n", NULL);
- return -1;
- }
-
- switch (id) {
- case ATTRIB_COUNTRY_NAME:
- if (attribs->country) {
- psFree(attribs->country);
- }
- attribs->country = stringOut;
- break;
- case ATTRIB_STATE_PROVINCE:
- if (attribs->state) {
- psFree(attribs->state);
- }
- attribs->state = stringOut;
- break;
- case ATTRIB_LOCALITY:
- if (attribs->locality) {
- psFree(attribs->locality);
- }
- attribs->locality = stringOut;
- break;
- case ATTRIB_ORGANIZATION:
- if (attribs->organization) {
- psFree(attribs->organization);
- }
- attribs->organization = stringOut;
- break;
- case ATTRIB_ORG_UNIT:
- if (attribs->orgUnit) {
- psFree(attribs->orgUnit);
- }
- attribs->orgUnit = stringOut;
- break;
- case ATTRIB_COMMON_NAME:
- if (attribs->commonName) {
- psFree(attribs->commonName);
- }
- attribs->commonName = stringOut;
- break;
-/*
- Not a MUST support
-*/
- default:
- psFree(stringOut);
- stringOut = NULL;
- break;
- }
-/*
- Hash up the DN. Nice for validation later
-*/
- if (stringOut != NULL) {
- matrixSha1Update(&hash, (unsigned char*)stringOut, llen);
- }
- }
- matrixSha1Final(&hash, (unsigned char*)attribs->hash);
- *pp = p;
- return 0;
-}
-
-/******************************************************************************/
-/*
- Get the BIT STRING key and plug into RSA structure. Not included in
- asn1.c because it deals directly with the sslRsaKey_t struct.
-*/
-int32 getPubKey(psPool_t *pool, unsigned char **pp, int32 len,
- sslRsaKey_t *pubKey)
-{
- unsigned char *p = *pp;
- int32 pubKeyLen, ignore_bits, seqLen;
-
- if (len < 1 || (*(p++) != ASN_BIT_STRING) ||
- asnParseLength(&p, len - 1, &pubKeyLen) < 0 ||
- (len - 1) < pubKeyLen) {
- return -1;
- }
-
- ignore_bits = *p++;
-/*
- We assume this is always zero
-*/
- sslAssert(ignore_bits == 0);
-
- if (getSequence(&p, pubKeyLen, &seqLen) < 0 ||
- getBig(pool, &p, seqLen, &pubKey->N) < 0 ||
- getBig(pool, &p, seqLen, &pubKey->e) < 0) {
- return -1;
- }
- pubKey->size = mp_unsigned_bin_size(&pubKey->N);
-
- *pp = p;
- return 0;
-}
-
-/******************************************************************************/
-/*
- Free helper
-*/
-void psFreeDNStruct(DNattributes_t *dn)
-{
- if (dn->country) psFree(dn->country);
- if (dn->state) psFree(dn->state);
- if (dn->locality) psFree(dn->locality);
- if (dn->organization) psFree(dn->organization);
- if (dn->orgUnit) psFree(dn->orgUnit);
- if (dn->commonName) psFree(dn->commonName);
-}
-
-
-/******************************************************************************/
diff --git a/release/src/router/matrixssl/src/pki/x509.c b/release/src/router/matrixssl/src/pki/x509.c
deleted file mode 100644
index fdd3e678..00000000
--- a/release/src/router/matrixssl/src/pki/x509.c
+++ /dev/null
@@ -1,1699 +0,0 @@
-/*
- * x509.c
- * Release $Name: MATRIXSSL_1_8_8_OPEN $
- *
- * DER/BER coding
- */
-/*
- * Copyright (c) PeerSec Networks, 2002-2009. All Rights Reserved.
- * The latest version of this code is available at http://www.matrixssl.org
- *
- * This software is open source; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This General Public License does NOT permit incorporating this software
- * into proprietary programs. If you are unable to comply with the GPL, a
- * commercial license for this software may be purchased from PeerSec Networks
- * at http://www.peersec.com
- *
- * This program is distributed in WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * http://www.gnu.org/copyleft/gpl.html
- */
-/******************************************************************************/
-
-#include "pkiInternal.h"
-
-/*
- X509 is wrapped in USE_RSA until more key types are added
-*/
-#ifdef USE_RSA
-#ifdef USE_X509
-
-#define IMPLICIT_ISSUER_ID 1
-#define IMPLICIT_SUBJECT_ID 2
-#define EXPLICIT_EXTENSION 3
-
-#define RSA_SIG 1
-#define DSA_SIG 2
-
-#define OID_SHA1 88
-#define OID_MD2 646
-#define OID_MD5 649
-
-/*
- Certificate extension hash mappings
-*/
-#define EXT_BASIC_CONSTRAINTS 1
-#define EXT_KEY_USAGE 2
-#define EXT_SUBJ_KEY_ID 3
-#define EXT_AUTH_KEY_ID 4
-#define EXT_ALT_SUBJECT_NAME 5
-
-static const struct {
- unsigned char hash[16];
- int32 id;
-} extTable[] = {
- { { 0xa5, 0xc4, 0x5e, 0x9a, 0xa3, 0xbb, 0x71, 0x2f, 0x07,
- 0xf7, 0x4c, 0xd0, 0xcd, 0x95, 0x65, 0xda }, EXT_BASIC_CONSTRAINTS },
- { { 0xf5, 0xab, 0x88, 0x49, 0xc4, 0xfd, 0xa2, 0x64, 0x6d,
- 0x06, 0xa2, 0x3e, 0x83, 0x9b, 0xef, 0xbb }, EXT_KEY_USAGE },
- { { 0x91, 0x54, 0x28, 0xcc, 0x81, 0x59, 0x8c, 0x71, 0x8c,
- 0x53, 0xa8, 0x4d, 0xeb, 0xd3, 0xc2, 0x18 }, EXT_SUBJ_KEY_ID },
- { { 0x48, 0x2d, 0xff, 0x49, 0xf7, 0xab, 0x93, 0xe8, 0x1f,
- 0x57, 0xb5, 0xaf, 0x7f, 0xaa, 0x31, 0xbb }, EXT_AUTH_KEY_ID },
- { { 0x5c, 0x70, 0xcb, 0xf5, 0xa4, 0x07, 0x5a, 0xcc, 0xd1,
- 0x55, 0xd2, 0x44, 0xdd, 0x62, 0x2c, 0x0c }, EXT_ALT_SUBJECT_NAME },
- { { 0 }, -1 } /* Must be last for proper termination */
-};
-
-
-static int32 getExplicitExtensions(psPool_t *pool, unsigned char **pp,
- int32 len, int32 expVal,
- v3extensions_t *extensions);
-static int32 matrixX509ValidateCertInternal(psPool_t *pool,
- sslCert_t *subjectCert, sslCert_t *issuerCert, int32 chain);
-#ifdef USE_FILE_SYSTEM
-static int32 parseList(psPool_t *pool, const char *list, const char *sep,
- char **item);
-#endif /* USE_FILE_SYSTEM */
-
-/******************************************************************************/
-/*
- Read in the certificate and private keys from the given files
- If privPass is non-NULL, it will be used to decode an encrypted private
- key file.
-
- The certificate is stored internally as a pointer to DER encoded X.509
- The private key is stored in a crypto provider specific structure
-*/
-#ifdef USE_FILE_SYSTEM
-int32 matrixX509ReadKeys(sslKeys_t **keys, const char *certFile,
- const char *privFile, const char *privPass,
- const char *trustedCAFiles)
-{
- return matrixX509ReadKeysEx(PEERSEC_BASE_POOL, keys, certFile, privFile,
- privPass, trustedCAFiles);
-}
-#else /* USE_FILE_SYSTEM */
-int32 matrixX509ReadKeys(sslKeys_t **keys, char *certFile, char *privFile,
- char *privPass, char *trustedCAFile)
-{
- matrixStrDebugMsg("Error: Calling matrixX509ReadKeys against a library " \
- "built without USE_FILE_SYSTEM defined\n", NULL);
- return -1;
-}
-#endif /* USE_FILE_SYSTEM */
-
-/******************************************************************************/
-/*
- In memory version of matrixX509ReadKeys. The buffers are the ASN.1 raw
- stream (ie. not base64 PEM encoded)
-
- API CHANGE: 1.7 changed this protoype and buffer formats (ASN.1 now) but
- this function was never properly documented. Users who may have found
- this function on their own and are using it will need to convert to this
- new version.
-*/
-int32 matrixX509ReadKeysMem(sslKeys_t **keys, unsigned char *certBuf,
- int32 certLen, unsigned char *privBuf, int32 privLen,
- unsigned char *trustedCABuf, int32 trustedCALen)
-{
- return matrixRsaParseKeysMem(PEERSEC_BASE_POOL, keys, certBuf, certLen,
- privBuf, privLen, trustedCABuf, trustedCALen);
-}
-
-/******************************************************************************/
-/*
- Free private key and cert and zero memory allocated by matrixSslReadKeys.
-*/
-void matrixRsaFreeKeys(sslKeys_t *keys)
-{
- sslLocalCert_t *current, *next;
- int32 i = 0;
-
- if (keys) {
- current = &keys->cert;
- while (current) {
- if (current->certBin) {
- memset(current->certBin, 0x0, current->certLen);
- psFree(current->certBin);
- }
- if (current->privKey) {
- matrixRsaFreeKey(current->privKey);
- }
- next = current->next;
- if (i++ > 0) {
- psFree(current);
- }
- current = next;
- }
-#ifdef USE_CLIENT_SIDE_SSL
- if (keys->caCerts) {
- matrixX509FreeCert(keys->caCerts);
- }
-#endif /* USE_CLIENT_SIDE_SSL */
- psFree(keys);
- }
-}
-
-#ifdef USE_FILE_SYSTEM
-/******************************************************************************/
-/*
- Preferred version for commercial users who make use of memory pools.
-
- This use of the sslKeys_t param implies this is for use in the MatrixSSL
- product (input to matrixSslNewSession). However, we didn't want to
- expose this API at the matrixSsl.h level due to the pool parameter. This
- is strictly an API that commerical users will have access to
-*/
-int32 matrixX509ReadKeysEx(psPool_t *pool, sslKeys_t **keys,
- const char *certFile, const char *privFile,
- const char *privPass, const char *trustedCAFiles)
-{
- sslKeys_t *lkeys;
- unsigned char *privKeyMem;
- int32 rc, privKeyMemLen;
-#ifdef USE_CLIENT_SIDE_SSL
- sslCert_t *currCert, *prevCert = NULL;
- unsigned char *caCert, *caStream;
- sslChainLen_t chain;
- int32 caCertLen, first, i;
-#endif /* USE_CLIENT_SIDE_SSL */
-
- *keys = lkeys = psMalloc(pool, sizeof(sslKeys_t));
- if (lkeys == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memset(lkeys, 0x0, sizeof(sslKeys_t));
-/*
- Load certificate files. Any additional certificate files should chain
- to the root CA held on the other side.
-*/
- rc = readCertChain(pool, certFile, &lkeys->cert);
- if (rc < 0 ) {
- matrixRsaFreeKeys(lkeys);
- return rc;
- }
-/*
- The first cert in certFile must be associated with the provided
- private key.
-*/
- if (privFile) {
- rc = matrixX509ReadPrivKey(pool, privFile, privPass, &privKeyMem,
- &privKeyMemLen);
- if (rc < 0) {
- matrixStrDebugMsg("Error reading private key file: %s\n",
- (char*)privFile);
- matrixRsaFreeKeys(lkeys);
- return rc;
- }
- rc = matrixRsaParsePrivKey(pool, privKeyMem, privKeyMemLen,
- &lkeys->cert.privKey);
- if (rc < 0) {
- matrixStrDebugMsg("Error parsing private key file: %s\n",
- (char*)privFile);
- psFree(privKeyMem);
- matrixRsaFreeKeys(lkeys);
- return rc;
- }
- psFree(privKeyMem);
- }
-
-#ifdef USE_CLIENT_SIDE_SSL
-/*
- Now deal with Certificate Authorities
-*/
- if (trustedCAFiles != NULL) {
- if (matrixX509ReadCert(pool, trustedCAFiles, &caCert, &caCertLen,
- &chain) < 0 || caCert == NULL) {
- matrixStrDebugMsg("Error reading CA cert files %s\n",
- (char*)trustedCAFiles);
- matrixRsaFreeKeys(lkeys);
- return -1;
- }
-
- caStream = caCert;
- i = first = 0;
- while (chain[i] != 0) {
-/*
- Don't allow one bad cert to ruin the whole bunch if possible
-*/
- if (matrixX509ParseCert(pool, caStream, chain[i], &currCert) < 0) {
- matrixX509FreeCert(currCert);
- matrixStrDebugMsg("Error parsing CA cert %s\n",
- (char*)trustedCAFiles);
- caStream += chain[i]; caCertLen -= chain[i];
- i++;
- continue;
- }
-
- if (first == 0) {
- lkeys->caCerts = currCert;
- } else {
- prevCert->next = currCert;
- }
- first++;
- prevCert = currCert;
- currCert = NULL;
- caStream += chain[i]; caCertLen -= chain[i];
- i++;
- }
- sslAssert(caCertLen == 0);
- psFree(caCert);
- }
-/*
- Check to see that if a set of CAs were passed in at least
- one ended up being valid.
-*/
- if (trustedCAFiles != NULL && lkeys->caCerts == NULL) {
- matrixStrDebugMsg("No valid CA certs in %s\n",
- (char*)trustedCAFiles);
- matrixRsaFreeKeys(lkeys);
- return -1;
- }
-#endif /* USE_CLIENT_SIDE_SSL */
- return 0;
-}
-
-/******************************************************************************/
-/*
- * Public API to return a binary buffer from a cert. Suitable to send
- * over the wire. Caller must free 'out' if this function returns success (0)
- * Parse .pem files according to http://www.faqs.org/rfcs/rfc1421.html
- */
-int32 matrixX509ReadCert(psPool_t *pool, const char *fileName,
- unsigned char **out, int32 *outLen, sslChainLen_t *chain)
-{
- int32 certBufLen, rc, certChainLen, i;
- unsigned char *oneCert[MAX_CHAIN_LENGTH];
- unsigned char *certPtr, *tmp;
- char *certFile, *start, *end, *certBuf, *endTmp;
- const char sep[] = ";";
-
-/*
- Init chain array and output params
-*/
- for (i=0; i < MAX_CHAIN_LENGTH; i++) {
- oneCert[i] = NULL;
- (*chain)[i] = 0;
- }
- *outLen = certChainLen = i = 0;
- rc = -1;
-
-/*
- For PKI product purposes, this routine now accepts a chain of certs.
-*/
- if (fileName != NULL) {
- fileName += parseList(pool, fileName, sep, &certFile);
- } else {
- return 0;
- }
-
- while (certFile != NULL) {
-
- if (i == MAX_CHAIN_LENGTH) {
- matrixIntDebugMsg("Exceeded maximum cert chain length of %d\n",
- MAX_CHAIN_LENGTH);
- psFree(certFile);
- rc = -1;
- goto err;
- }
- if ((rc = psGetFileBin(pool, certFile, (unsigned char**)&certBuf,
- &certBufLen)) < 0) {
- matrixStrDebugMsg("Couldn't open file %s\n", certFile);
- goto err;
- }
- psFree(certFile);
- certPtr = (unsigned char*)certBuf;
- start = end = endTmp = certBuf;
-
- while (certBufLen > 0) {
- if (((start = strstr(certBuf, "-----BEGIN")) != NULL) &&
- ((start = strstr(certBuf, "CERTIFICATE-----")) != NULL) &&
- ((end = strstr(start, "-----END")) != NULL) &&
- ((endTmp = strstr(end,"CERTIFICATE-----")) != NULL)) {
- start += strlen("CERTIFICATE-----");
- (*chain)[i] = (int32)(end - start);
- end = endTmp + strlen("CERTIFICATE-----");
- while (*end == '\r' || *end == '\n' || *end == '\t'
- || *end == ' ') {
- end++;
- }
- } else {
- psFree(certPtr);
- rc = -1;
- goto err;
- }
- oneCert[i] = psMalloc(pool, (*chain)[i]);
- certBufLen -= (int32)(end - certBuf);
- certBuf = end;
- memset(oneCert[i], '\0', (*chain)[i]);
-
- if (ps_base64_decode((unsigned char*)start, (*chain)[i], oneCert[i],
- &(*chain)[i]) != 0) {
- psFree(certPtr);
- matrixStrDebugMsg("Unable to base64 decode certificate\n", NULL);
- rc = -1;
- goto err;
- }
- certChainLen += (*chain)[i];
- i++;
- if (i == MAX_CHAIN_LENGTH) {
- matrixIntDebugMsg("Exceeded maximum cert chain length of %d\n",
- MAX_CHAIN_LENGTH);
- psFree(certPtr);
- rc = -1;
- goto err;
- }
- }
- psFree(certPtr);
-/*
- Check for more files
-*/
- fileName += parseList(pool, fileName, sep, &certFile);
- }
-
- *outLen = certChainLen;
-/*
- Don't bother stringing them together if only one was passed in
-*/
- if (i == 1) {
- sslAssert(certChainLen == (*chain)[0]);
- *out = oneCert[0];
- return 0;
- } else {
- *out = tmp = psMalloc(pool, certChainLen);
- for (i=0; i < MAX_CHAIN_LENGTH; i++) {
- if (oneCert[i]) {
- memcpy(tmp, oneCert[i], (*chain)[i]);
- tmp += (*chain)[i];
- }
- }
- rc = 0;
- }
-
-err:
- for (i=0; i < MAX_CHAIN_LENGTH; i++) {
- if (oneCert[i]) psFree(oneCert[i]);
- }
- return rc;
-}
-
-/******************************************************************************/
-/*
- This function was written strictly for clarity in the PeerSec crypto API
- product. It extracts only the public key from a certificate file for use
- in the lower level encrypt/decrypt RSA routines
-*/
-int32 matrixX509ReadPubKey(psPool_t *pool, const char *certFile,
- sslRsaKey_t **key)
-{
- unsigned char *certBuf;
- sslChainLen_t chain;
- int32 certBufLen;
-
- certBuf = NULL;
- if (matrixX509ReadCert(pool, certFile, &certBuf, &certBufLen, &chain) < 0) {
- matrixStrDebugMsg("Unable to read certificate file %s\n",
- (char*)certFile);
- if (certBuf) psFree(certBuf);
- return -1;
- }
- if (matrixX509ParsePubKey(pool, certBuf, certBufLen, key) < 0) {
- psFree(certBuf);
- return -1;
- }
- psFree(certBuf);
- return 0;
-}
-
-/******************************************************************************/
-/*
- Allows for semi-colon delimited list of certificates for cert chaining.
- Also allows multiple certificiates in a single file.
-
- HOWERVER, in both cases the first in the list must be the identifying
- cert of the application. Each subsequent cert is the parent of the previous
-*/
-int32 readCertChain(psPool_t *pool, const char *certFiles,
- sslLocalCert_t *lkeys)
-{
- sslLocalCert_t *currCert;
- unsigned char *certBin, *tmp;
- sslChainLen_t chain;
- int32 certLen, i;
-
- if (certFiles == NULL) {
- return 0;
- }
-
- if (matrixX509ReadCert(pool, certFiles, &certBin, &certLen, &chain) < 0) {
- matrixStrDebugMsg("Error reading cert file %s\n", (char*)certFiles);
- return -1;
- }
-/*
- The first cert is allocated in the keys struct. All others in
- linked list are allocated here.
-*/
- i = 0;
- tmp = certBin;
- while (chain[i] != 0) {
- if (i == 0) {
- currCert = lkeys;
- } else {
- currCert->next = psMalloc(pool, sizeof(sslLocalCert_t));
- if (currCert->next == NULL) {
- psFree(tmp);
- return -8; /* SSL_MEM_ERROR */
- }
- memset(currCert->next, 0x0, sizeof(sslLocalCert_t));
- currCert = currCert->next;
- }
- currCert->certBin = psMalloc(pool, chain[i]);
- memcpy(currCert->certBin, certBin, chain[i]);
- currCert->certLen = chain[i];
- certBin += chain[i]; certLen -= chain[i];
- i++;
- }
- psFree(tmp);
- sslAssert(certLen == 0);
- return 0;
-}
-
-/******************************************************************************/
-/*
- * Strtok substitute
- */
-static int32 parseList(psPool_t *pool, const char *list, const char *sep,
- char **item)
-{
- int32 start, listLen;
- char *tmp;
-
- start = listLen = (int32)strlen(list) + 1;
- if (start == 1) {
- *item = NULL;
- return 0;
- }
- tmp = *item = psMalloc(pool, listLen);
- if (tmp == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memset(*item, 0, listLen);
- while (listLen > 0) {
- if (*list == sep[0]) {
- list++;
- listLen--;
- break;
- }
- if (*list == 0) {
- break;
- }
- *tmp++ = *list++;
- listLen--;
- }
- return start - listLen;
-}
-#endif /* USE_FILE_SYSTEM */
-
-
-/******************************************************************************/
-/*
- Preferred version for commercial users who make use of memory pools.
-
- This use of the sslKeys_t param implies this is for use in the MatrixSSL
- product (input to matrixSslNewSession). However, we didn't want to
- expose this API at the matrixSsl.h level due to the pool parameter. This
- is strictly an API that commerical users will have access to.
-*/
-int32 matrixRsaParseKeysMem(psPool_t *pool, sslKeys_t **keys,
- unsigned char *certBuf, int32 certLen, unsigned char *privBuf,
- int32 privLen, unsigned char *trustedCABuf, int32 trustedCALen)
-{
- sslKeys_t *lkeys;
- sslLocalCert_t *current, *next;
- unsigned char *binPtr;
- int32 len, lenOh, i;
-#ifdef USE_CLIENT_SIDE_SSL
- sslCert_t *currentCA, *nextCA;
-#endif /* USE_CLIENT_SIDE_SSL */
-
- *keys = lkeys = psMalloc(pool, sizeof(sslKeys_t));
- if (lkeys == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memset(lkeys, 0x0, sizeof(sslKeys_t));
-/*
- The buffers are just the ASN.1 streams so the intermediate parse
- that used to be here is gone. Doing a straight memcpy for this
- and passing that along to X509ParseCert
-*/
- i = 0;
- current = &lkeys->cert;
- binPtr = certBuf;
-/*
- Need to check for a chain here. Only way to do this is to read off the
- length id from the DER stream for each. The chain must be just a stream
- of DER certs with the child-most cert always first.
-*/
- while (certLen > 0) {
- if (getSequence(&certBuf, certLen, &len) < 0) {
- matrixStrDebugMsg("Unable to parse length of cert stream\n", NULL);
- matrixRsaFreeKeys(lkeys);
- return -1;
- }
-/*
- Account for the overhead of storing the length itself
-*/
- lenOh = (int32)(certBuf - binPtr);
- len += lenOh;
- certBuf -= lenOh;
-/*
- First cert is already malloced
-*/
- if (i > 0) {
- next = psMalloc(pool, sizeof(sslLocalCert_t));
- memset(next, 0x0, sizeof(sslLocalCert_t));
- current->next = next;
- current = next;
- }
- current->certBin = psMalloc(pool, len);
- memcpy(current->certBin, certBuf, len);
- current->certLen = len;
- certLen -= len;
- certBuf += len;
- binPtr = certBuf;
- i++;
- }
-
-/*
- Parse private key
-*/
- if (privLen > 0) {
- if (matrixRsaParsePrivKey(pool, privBuf, privLen,
- &lkeys->cert.privKey) < 0) {
- matrixStrDebugMsg("Error reading private key mem\n", NULL);
- matrixRsaFreeKeys(lkeys);
- return -1;
- }
- }
-
-
-/*
- Trusted CAs
-*/
-#ifdef USE_CLIENT_SIDE_SSL
- if (trustedCABuf != NULL && trustedCALen > 0) {
- i = 0;
- binPtr = trustedCABuf;
- currentCA = NULL;
-/*
- Need to check for list here. Only way to do this is to read off the
- length id from the DER stream for each.
-*/
- while (trustedCALen > 0) {
- if (getSequence(&trustedCABuf, trustedCALen, &len) < 0) {
- matrixStrDebugMsg("Unable to parse length of CA stream\n",
- NULL);
- matrixRsaFreeKeys(lkeys);
- return -1;
- }
-/*
- Account for the overhead of storing the length itself
-*/
- lenOh = (int32)(trustedCABuf - binPtr);
- len += lenOh;
- trustedCABuf -= lenOh;
-
- if (matrixX509ParseCert(pool, trustedCABuf, len, &currentCA) < 0) {
- matrixX509FreeCert(currentCA);
- matrixStrDebugMsg("Error parsing CA cert\n", NULL);
- matrixRsaFreeKeys(lkeys);
- return -1;
- }
-/*
- First cert should be assigned to lkeys
-*/
- if (i == 0) {
- lkeys->caCerts = currentCA;
- nextCA = lkeys->caCerts;
- } else {
- nextCA->next = currentCA;
- nextCA = currentCA;
- }
- currentCA = currentCA->next;
- trustedCALen -= len;
- trustedCABuf += len;
- binPtr = trustedCABuf;
- i++;
- }
- }
-#endif /* USE_CLIENT_SIDE_SSL */
-
- return 0;
-}
-
-/******************************************************************************/
-/*
- In-memory version of matrixX509ReadPubKey.
- This function was written strictly for clarity in the PeerSec crypto API
- subset. It extracts only the public key from a certificate file for use
- in the lower level encrypt/decrypt RSA routines.
-*/
-int32 matrixX509ParsePubKey(psPool_t *pool, unsigned char *certBuf,
- int32 certLen, sslRsaKey_t **key)
-{
- sslRsaKey_t *lkey;
- sslCert_t *certStruct;
- int32 err;
-
- if (matrixX509ParseCert(pool, certBuf, certLen, &certStruct) < 0) {
- matrixX509FreeCert(certStruct);
- return -1;
- }
- lkey = *key = psMalloc(pool, sizeof(sslRsaKey_t));
- memset(lkey, 0x0, sizeof(sslRsaKey_t));
-
- if ((err = _mp_init_multi(pool, &lkey->e, &lkey->N, NULL,
- NULL, NULL, NULL, NULL, NULL)) != MP_OKAY) {
- matrixX509FreeCert(certStruct);
- psFree(lkey);
- return err;
- }
- mp_copy(&certStruct->publicKey.e, &lkey->e);
- mp_copy(&certStruct->publicKey.N, &lkey->N);
-
- mp_shrink(&lkey->e);
- mp_shrink(&lkey->N);
-
- lkey->size = certStruct->publicKey.size;
-
- matrixX509FreeCert(certStruct);
-
- return 0;
-}
-
-
-/******************************************************************************/
-/*
- Parse an X509 ASN.1 certificate stream
- http://www.faqs.org/rfcs/rfc2459.html section 4.1
-*/
-int32 matrixX509ParseCert(psPool_t *pool, unsigned char *pp, int32 size,
- sslCert_t **outcert)
-{
- sslCert_t *cert;
- sslMd5Context_t md5Ctx;
- sslSha1Context_t sha1Ctx;
- unsigned char *p, *end, *certStart, *certEnd;
- int32 certLen, len, parsing;
-#ifdef USE_MD2
- sslMd2Context_t md2Ctx;
-#endif /* USE_MD2 */
-
-/*
- Allocate the cert structure right away. User MUST always call
- matrixX509FreeCert regardless of whether this function succeeds.
- memset is important because the test for NULL is what is used
- to determine what to free
-*/
- *outcert = cert = psMalloc(pool, sizeof(sslCert_t));
- if (cert == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memset(cert, '\0', sizeof(sslCert_t));
-
- p = pp;
- end = p + size;
-/*
- Certificate ::= SEQUENCE {
- tbsCertificate TBSCertificate,
- signatureAlgorithm AlgorithmIdentifier,
- signatureValue BIT STRING }
-*/
- parsing = 1;
- while (parsing) {
- if (getSequence(&p, (int32)(end - p), &len) < 0) {
- matrixStrDebugMsg("Initial cert parse error\n", NULL);
- return -1;
- }
- certStart = p;
-/*
- TBSCertificate ::= SEQUENCE {
- version [0] EXPLICIT Version DEFAULT v1,
- serialNumber CertificateSerialNumber,
- signature AlgorithmIdentifier,
- issuer Name,
- validity Validity,
- subject Name,
- subjectPublicKeyInfo SubjectPublicKeyInfo,
- issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
- -- If present, version shall be v2 or v3
- subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
- -- If present, version shall be v2 or v3
- extensions [3] EXPLICIT Extensions OPTIONAL
- -- If present, version shall be v3 }
-*/
- if (getSequence(&p, (int32)(end - p), &len) < 0) {
- matrixStrDebugMsg("ASN sequence parse error\n", NULL);
- return -1;
- }
- certEnd = p + len;
- certLen = (int32)(certEnd - certStart);
-
-/*
- Version ::= INTEGER { v1(0), v2(1), v3(2) }
-*/
- if (getExplicitVersion(&p, (int32)(end - p), 0, &cert->version) < 0) {
- matrixStrDebugMsg("ASN version parse error\n", NULL);
- return -1;
- }
- if (cert->version != 2) {
- matrixIntDebugMsg("Warning: non-v3 certificate version: %d\n",
- cert->version);
- }
-/*
- CertificateSerialNumber ::= INTEGER
-*/
- if (getSerialNum(pool, &p, (int32)(end - p), &cert->serialNumber,
- &cert->serialNumberLen) < 0) {
- matrixStrDebugMsg("ASN serial number parse error\n", NULL);
- return -1;
- }
-/*
- AlgorithmIdentifier ::= SEQUENCE {
- algorithm OBJECT IDENTIFIER,
- parameters ANY DEFINED BY algorithm OPTIONAL }
-*/
- if (getAlgorithmIdentifier(&p, (int32)(end - p),
- &cert->certAlgorithm, 0) < 0) {
- return -1;
- }
-/*
- Name ::= CHOICE {
- RDNSequence }
-
- RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
-
- RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
-
- AttributeTypeAndValue ::= SEQUENCE {
- type AttributeType,
- value AttributeValue }
-
- AttributeType ::= OBJECT IDENTIFIER
-
- AttributeValue ::= ANY DEFINED BY AttributeType
-*/
- if (getDNAttributes(pool, &p, (int32)(end - p), &cert->issuer) < 0) {
- return -1;
- }
-/*
- Validity ::= SEQUENCE {
- notBefore Time,
- notAfter Time }
-*/
- if (getValidity(pool, &p, (int32)(end - p), &cert->notBefore,
- &cert->notAfter) < 0) {
- return -1;
- }
-/*
- Subject DN
-*/
- if (getDNAttributes(pool, &p, (int32)(end - p), &cert->subject) < 0) {
- return -1;
- }
-/*
- SubjectPublicKeyInfo ::= SEQUENCE {
- algorithm AlgorithmIdentifier,
- subjectPublicKey BIT STRING }
-*/
- if (getSequence(&p, (int32)(end - p), &len) < 0) {
- return -1;
- }
- if (getAlgorithmIdentifier(&p, (int32)(end - p),
- &cert->pubKeyAlgorithm, 1) < 0) {
- return -1;
- }
-
- if (getPubKey(pool, &p, (int32)(end - p), &cert->publicKey) < 0) {
- return -1;
- }
-
-/*
- As the next three values are optional, we can do a specific test here
-*/
- if (*p != (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
- if (getImplicitBitString(pool, &p, (int32)(end - p), IMPLICIT_ISSUER_ID,
- &cert->uniqueUserId, &cert->uniqueUserIdLen) < 0 ||
- getImplicitBitString(pool, &p, (int32)(end - p), IMPLICIT_SUBJECT_ID,
- &cert->uniqueSubjectId, &cert->uniqueSubjectIdLen) < 0 ||
- getExplicitExtensions(pool, &p, (int32)(end - p), EXPLICIT_EXTENSION,
- &cert->extensions) < 0) {
- matrixStrDebugMsg("There was an error parsing a certificate\n", NULL);
- matrixStrDebugMsg("extension. This is likely caused by an\n", NULL);
- matrixStrDebugMsg("extension format that is not currently\n", NULL);
- matrixStrDebugMsg("recognized. Please email support@peersec.com\n", NULL);
- matrixStrDebugMsg("to add support for the extension.\n\n", NULL);
- return -1;
- }
- }
-/*
- This is the end of the cert. Do a check here to be certain
-*/
- if (certEnd != p) {
- return -1;
- }
-/*
- Certificate signature info
-*/
- if (getAlgorithmIdentifier(&p, (int32)(end - p),
- &cert->sigAlgorithm, 0) < 0) {
- return -1;
- }
-/*
- Signature algorithm must match that specified in TBS cert
-*/
- if (cert->certAlgorithm != cert->sigAlgorithm) {
- matrixStrDebugMsg("Parse error: mismatched signature type\n", NULL);
- return -1;
- }
-/*
- Compute the hash of the cert here for CA validation
-*/
- if (cert->certAlgorithm == OID_RSA_MD5) {
- matrixMd5Init(&md5Ctx);
- matrixMd5Update(&md5Ctx, certStart, certLen);
- matrixMd5Final(&md5Ctx, cert->sigHash);
- } else if (cert->certAlgorithm == OID_RSA_SHA1) {
- matrixSha1Init(&sha1Ctx);
- matrixSha1Update(&sha1Ctx, certStart, certLen);
- matrixSha1Final(&sha1Ctx, cert->sigHash);
- }
-#ifdef USE_MD2
- else if (cert->certAlgorithm == OID_RSA_MD2) {
- matrixMd2Init(&md2Ctx);
- matrixMd2Update(&md2Ctx, certStart, certLen);
- matrixMd2Final(&md2Ctx, cert->sigHash);
- }
-#endif /* USE_MD2 */
-
- if (getSignature(pool, &p, (int32)(end - p), &cert->signature,
- &cert->signatureLen) < 0) {
- return -1;
- }
-/*
- The ability to parse additional chained certs is a PKI product
- feature addition. Chaining in MatrixSSL is handled internally.
-*/
- if (p != end) {
- cert->next = psMalloc(pool, sizeof(sslCert_t));
- cert = cert->next;
- memset(cert, '\0', sizeof(sslCert_t));
- } else {
- parsing = 0;
- }
- }
-
- return (int32)(p - pp);
-}
-
-/******************************************************************************/
-/*
- User must call after all calls to matrixX509ParseCert
- (we violate the coding standard a bit here for clarity)
-*/
-void matrixX509FreeCert(sslCert_t *cert)
-{
- sslCert_t *curr, *next;
- sslSubjectAltName_t *active, *inc;
-
- curr = cert;
- while (curr) {
- psFreeDNStruct(&curr->issuer);
- psFreeDNStruct(&curr->subject);
- if (curr->serialNumber) psFree(curr->serialNumber);
- if (curr->notBefore) psFree(curr->notBefore);
- if (curr->notAfter) psFree(curr->notAfter);
- if (curr->publicKey.N.dp) mp_clear(&(curr->publicKey.N));
- if (curr->publicKey.e.dp) mp_clear(&(curr->publicKey.e));
- if (curr->signature) psFree(curr->signature);
- if (curr->uniqueUserId) psFree(curr->uniqueUserId);
- if (curr->uniqueSubjectId) psFree(curr->uniqueSubjectId);
-
- if (curr->extensions.san) {
- active = curr->extensions.san;
- while (active != NULL) {
- inc = active->next;
- psFree(active->data);
- psFree(active);
- active = inc;
- }
- }
-
-
-#ifdef USE_FULL_CERT_PARSE
- if (curr->extensions.keyUsage) psFree(curr->extensions.keyUsage);
- if (curr->extensions.sk.id) psFree(curr->extensions.sk.id);
- if (curr->extensions.ak.keyId) psFree(curr->extensions.ak.keyId);
- if (curr->extensions.ak.serialNum)
- psFree(curr->extensions.ak.serialNum);
- if (curr->extensions.ak.attribs.commonName)
- psFree(curr->extensions.ak.attribs.commonName);
- if (curr->extensions.ak.attribs.country)
- psFree(curr->extensions.ak.attribs.country);
- if (curr->extensions.ak.attribs.state)
- psFree(curr->extensions.ak.attribs.state);
- if (curr->extensions.ak.attribs.locality)
- psFree(curr->extensions.ak.attribs.locality);
- if (curr->extensions.ak.attribs.organization)
- psFree(curr->extensions.ak.attribs.organization);
- if (curr->extensions.ak.attribs.orgUnit)
- psFree(curr->extensions.ak.attribs.orgUnit);
-#endif /* SSL_FULL_CERT_PARSE */
- next = curr->next;
- psFree(curr);
- curr = next;
- }
-}
-
-/******************************************************************************/
-/*
- Do the signature validation for a subject certificate against a
- known CA certificate
-*/
-int32 psAsnConfirmSignature(unsigned char *sigHash, unsigned char *sigOut,
- int32 sigLen)
-{
- unsigned char *end, *p = sigOut;
- unsigned char hash[SSL_SHA1_HASH_SIZE];
- int32 len, oi;
-
- end = p + sigLen;
-/*
- DigestInfo ::= SEQUENCE {
- digestAlgorithm DigestAlgorithmIdentifier,
- digest Digest }
-
- DigestAlgorithmIdentifier ::= AlgorithmIdentifier
-
- Digest ::= OCTET STRING
-*/
- if (getSequence(&p, (int32)(end - p), &len) < 0) {
- return -1;
- }
-
-/*
- Could be MD5 or SHA1
- */
- if (getAlgorithmIdentifier(&p, (int32)(end - p), &oi, 0) < 0) {
- return -1;
- }
- if ((*p++ != ASN_OCTET_STRING) ||
- asnParseLength(&p, (int32)(end - p), &len) < 0 || (end - p) < len) {
- return -1;
- }
- memcpy(hash, p, len);
- if (oi == OID_MD5 || oi == OID_MD2) {
- if (len != SSL_MD5_HASH_SIZE) {
- return -1;
- }
- } else if (oi == OID_SHA1) {
- if (len != SSL_SHA1_HASH_SIZE) {
- return -1;
- }
- } else {
- return -1;
- }
-/*
- hash should match sigHash
-*/
- if (memcmp(hash, sigHash, len) != 0) {
- return -1;
- }
- return 0;
-}
-
-/******************************************************************************/
-/*
- Extension lookup
-*/
-static int32 lookupExt(unsigned char md5hash[SSL_MD5_HASH_SIZE])
-{
- int32 i, j;
- const unsigned char *tmp;
-
- for (i = 0; ;i++) {
- if (extTable[i].id == -1) {
- return -1;
- }
- tmp = extTable[i].hash;
- for (j = 0; j < SSL_MD5_HASH_SIZE; j++) {
- if (md5hash[j] != tmp[j]) {
- break;
- }
- if (j == SSL_MD5_HASH_SIZE - 1) {
- return extTable[i].id;
- }
- }
- }
-}
-
-/******************************************************************************/
-/*
- X509v3 extensions
-*/
-static int32 getExplicitExtensions(psPool_t *pool, unsigned char **pp,
- int32 inlen, int32 expVal,
- v3extensions_t *extensions)
-{
- unsigned char *p = *pp, *end;
- unsigned char *extEnd, *extStart;
- int32 len, noid, critical, fullExtLen;
- unsigned char oid[SSL_MD5_HASH_SIZE];
- sslMd5Context_t md5ctx;
- sslSubjectAltName_t *activeName, *prevName;
-
- end = p + inlen;
- if (inlen < 1) {
- return -1;
- }
-/*
- Not treating this as an error because it is optional.
-*/
- if (*p != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | expVal)) {
- return 0;
- }
- p++;
- if (asnParseLength(&p, (int32)(end - p), &len) < 0 || (end - p) < len) {
- return -1;
- }
-/*
- Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
-
- Extension ::= SEQUENCE {
- extnID OBJECT IDENTIFIER,
- extnValue OCTET STRING }
-*/
- if (getSequence(&p, (int32)(end - p), &len) < 0) {
- return -1;
- }
- extEnd = p + len;
- while ((p != extEnd) && *p == (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
- if (getSequence(&p, (int32)(extEnd - p), &fullExtLen) < 0) {
- return -1;
- }
- extStart = p;
-/*
- Conforming CAs MUST support key identifiers, basic constraints,
- key usage, and certificate policies extensions
-
- id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 }
- id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } 133
- id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
- id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 }
- id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } 131
-*/
- if (extEnd - p < 1 || *p++ != ASN_OID) {
- return -1;
- }
-
- if (asnParseLength(&p, (int32)(extEnd - p), &len) < 0 ||
- (extEnd - p) < len) {
- return -1;
- }
-/*
- Send the OID through a digest to get the unique id
-*/
- matrixMd5Init(&md5ctx);
- while (len-- > 0) {
- matrixMd5Update(&md5ctx, p, sizeof(char));
- p++;
- }
- matrixMd5Final(&md5ctx, oid);
- noid = lookupExt(oid);
-
-/*
- Possible boolean value here for 'critical' id. It's a failure if a
- critical extension is found that is not supported
-*/
- critical = 0;
- if (*p == ASN_BOOLEAN) {
- p++;
- if (*p++ != 1) {
- matrixStrDebugMsg("Error parsing cert extension\n", NULL);
- return -1;
- }
- if (*p++ > 0) {
- critical = 1;
- }
- }
- if (extEnd - p < 1 || (*p++ != ASN_OCTET_STRING) ||
- asnParseLength(&p, (int32)(extEnd - p), &len) < 0 ||
- extEnd - p < len) {
- matrixStrDebugMsg("Expecting OCTET STRING in ext parse\n", NULL);
- return -1;
- }
-
- switch (noid) {
-/*
- BasicConstraints ::= SEQUENCE {
- cA BOOLEAN DEFAULT FALSE,
- pathLenConstraint INTEGER (0..MAX) OPTIONAL }
-*/
- case EXT_BASIC_CONSTRAINTS:
- if (getSequence(&p, (int32)(extEnd - p), &len) < 0) {
- return -1;
- }
-/*
- "This goes against PKIX guidelines but some CAs do it and some
- software requires this to avoid interpreting an end user
- certificate as a CA."
- - OpenSSL certificate configuration doc
-
- basicConstraints=CA:FALSE
-*/
- if (len == 0) {
- break;
- }
-/*
- Have seen some certs that don't include a cA bool.
-*/
- if (*p == ASN_BOOLEAN) {
- p++;
- if (*p++ != 1) {
- return -1;
- }
- extensions->bc.ca = *p++;
- } else {
- extensions->bc.ca = 0;
- }
-/*
- Now need to check if there is a path constraint. Only makes
- sense if cA is true. If it's missing, there is no limit to
- the cert path
-*/
- if (*p == ASN_INTEGER) {
- if (getInteger(&p, (int32)(extEnd - p),
- &(extensions->bc.pathLenConstraint)) < 0) {
- return -1;
- }
- } else {
- extensions->bc.pathLenConstraint = -1;
- }
- break;
- case EXT_ALT_SUBJECT_NAME:
- if (getSequence(&p, (int32)(extEnd - p), &len) < 0) {
- return -1;
- }
-/*
- Looking only for DNS, URI, and email here to support
- FQDN for Web clients
-
- FUTURE: Support all subject alt name members
- GeneralName ::= CHOICE {
- otherName [0] OtherName,
- rfc822Name [1] IA5String,
- dNSName [2] IA5String,
- x400Address [3] ORAddress,
- directoryName [4] Name,
- ediPartyName [5] EDIPartyName,
- uniformResourceIdentifier [6] IA5String,
- iPAddress [7] OCTET STRING,
- registeredID [8] OBJECT IDENTIFIER }
-*/
- while (len > 0) {
- if (extensions->san == NULL) {
- activeName = extensions->san = psMalloc(pool,
- sizeof(sslSubjectAltName_t));
- } else {
-/*
- Find the end
-*/
- prevName = extensions->san;
- activeName = prevName->next;
- while (activeName != NULL) {
- prevName = activeName;
- activeName = prevName->next;
- }
- prevName->next = psMalloc(pool,
- sizeof(sslSubjectAltName_t));
- activeName = prevName->next;
- }
- activeName->next = NULL;
- activeName->data = NULL;
- memset(activeName->name, '\0', 16);
-
- activeName->id = *p & 0xF;
- switch (activeName->id) {
- case 0:
- memcpy(activeName->name, "other", 5);
- break;
- case 1:
- memcpy(activeName->name, "email", 5);
- break;
- case 2:
- memcpy(activeName->name, "DNS", 3);
- break;
- case 3:
- memcpy(activeName->name, "x400Address", 11);
- break;
- case 4:
- memcpy(activeName->name, "directoryName", 13);
- break;
- case 5:
- memcpy(activeName->name, "ediPartyName", 12);
- break;
- case 6:
- memcpy(activeName->name, "URI", 3);
- break;
- case 7:
- memcpy(activeName->name, "iPAddress", 9);
- break;
- case 8:
- memcpy(activeName->name, "registeredID", 12);
- break;
- default:
- memcpy(activeName->name, "unknown", 7);
- break;
- }
-
- p++;
- activeName->dataLen = *p++;
- if (extEnd - p < activeName->dataLen) {
- return -1;
- }
- activeName->data = psMalloc(pool, activeName->dataLen + 1);
- if (activeName->data == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memset(activeName->data, 0x0, activeName->dataLen + 1);
- memcpy(activeName->data, p, activeName->dataLen);
-
- p = p + activeName->dataLen;
- /* the magic 2 is the type and length */
- len -= activeName->dataLen + 2;
- }
- break;
-#ifdef USE_FULL_CERT_PARSE
- case EXT_AUTH_KEY_ID:
-/*
- AuthorityKeyIdentifier ::= SEQUENCE {
- keyIdentifier [0] KeyIdentifier OPTIONAL,
- authorityCertIssuer [1] GeneralNames OPTIONAL,
- authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
-
- KeyIdentifier ::= OCTET STRING
-*/
- if (getSequence(&p, (int32)(extEnd - p), &len) < 0) {
- return -1;
- }
-/*
- Have seen a cert that has a zero length ext here. Let it pass.
-*/
- if (len == 0) {
- break;
- }
-/*
- All memebers are optional
-*/
- if (*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 0)) {
- p++;
- if (asnParseLength(&p, (int32)(extEnd - p),
- &extensions->ak.keyLen) < 0 ||
- extEnd - p < extensions->ak.keyLen) {
- return -1;
- }
- extensions->ak.keyId = psMalloc(pool, extensions->ak.keyLen);
- if (extensions->ak.keyId == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memcpy(extensions->ak.keyId, p, extensions->ak.keyLen);
- p = p + extensions->ak.keyLen;
- }
- if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) {
- p++;
- if (asnParseLength(&p, (int32)(extEnd - p), &len) < 0 ||
- len < 1 || extEnd - p < len) {
- return -1;
- }
- if ((*p ^ ASN_CONTEXT_SPECIFIC ^ ASN_CONSTRUCTED) != 4) {
-/*
- FUTURE: support other name types
- We are just dealing with DN formats here
-*/
- matrixIntDebugMsg("Error auth key-id name type: %d\n",
- *p ^ ASN_CONTEXT_SPECIFIC ^ ASN_CONSTRUCTED);
- return -1;
- }
- p++;
- if (asnParseLength(&p, (int32)(extEnd - p), &len) < 0 ||
- extEnd - p < len) {
- return -1;
- }
- if (getDNAttributes(pool, &p, (int32)(extEnd - p),
- &(extensions->ak.attribs)) < 0) {
- return -1;
- }
- }
- if ((*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2)) ||
- (*p == ASN_INTEGER)){
-/*
- Treat as a serial number (not a native INTEGER)
-*/
- if (getSerialNum(pool, &p, (int32)(extEnd - p),
- &(extensions->ak.serialNum), &len) < 0) {
- return -1;
- }
- extensions->ak.serialNumLen = len;
- }
- break;
-
- case EXT_KEY_USAGE:
-/*
- KeyUsage ::= BIT STRING {
- digitalSignature (0),
- nonRepudiation (1),
- keyEncipherment (2),
- dataEncipherment (3),
- keyAgreement (4),
- keyCertSign (5),
-
- cRLSign (6),
- encipherOnly (7),
- decipherOnly (8) }
-*/
- if (*p++ != ASN_BIT_STRING) {
- return -1;
- }
- if (asnParseLength(&p, (int32)(extEnd - p), &len) < 0 ||
- extEnd - p < len) {
- return -1;
- }
-/*
- We'd expect a length of 3 with the first byte being '07' to
- account for the trailing ignore bits in the second byte.
- But it doesn't appear all certificates adhere to the ASN.1
- encoding standard very closely. Just set it all aside for
- user to interpret as necessary.
-*/
- extensions->keyUsage = psMalloc(pool, len);
- memcpy(extensions->keyUsage, p, len);
- extensions->keyUsageLen = len;
- p = p + len;
- break;
- case EXT_SUBJ_KEY_ID:
-/*
- The value of the subject key identifier MUST be the value
- placed in the key identifier field of the Auth Key Identifier
- extension of certificates issued by the subject of
- this certificate.
-*/
- if (*p++ != ASN_OCTET_STRING || asnParseLength(&p,
- (int32)(extEnd - p), &(extensions->sk.len)) < 0 ||
- extEnd - p < extensions->sk.len) {
- return -1;
- }
- extensions->sk.id = psMalloc(pool, extensions->sk.len);
- if (extensions->sk.id == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memcpy(extensions->sk.id, p, extensions->sk.len);
- p = p + extensions->sk.len;
- break;
-#endif /* USE_FULL_CERT_PARSE */
-/*
- Unsupported or skipping because USE_FULL_CERT_PARSE is undefined
-*/
- default:
- if (critical) {
-/*
- SPEC DIFFERENCE: Ignoring an unrecognized critical
- extension. The specification dictates an error should
- occur, but real-world experience has shown this is not
- a realistic or desirable action. Also, no other SSL
- implementations have been found to error in this case.
- It is NOT a security risk in an RSA authenticaion sense.
-*/
- matrixStrDebugMsg("Unknown critical ext encountered\n",
- NULL);
- }
- p++;
-/*
- Skip over based on the length reported from the ASN_SEQUENCE
- surrounding the entire extension. It is not a guarantee that
- the value of the extension itself will contain it's own length.
-*/
- p = p + (fullExtLen - (p - extStart));
- break;
- }
- }
- *pp = p;
- return 0;
-}
-
-/******************************************************************************/
-/*
- Walk through the certificate chain and validate it. Return the final
- member of the chain as the subjectCert that can then be validated against
- the CAs. The subjectCert points into the chain param (no need to free)
-*/
-int32 matrixX509ValidateCertChain(psPool_t *pool, sslCert_t *chain,
- sslCert_t **subjectCert, int32 *valid)
-{
- sslCert_t *ic;
-
- *subjectCert = chain;
- *valid = 1;
- while ((*subjectCert)->next != NULL) {
- ic = (*subjectCert)->next;
- if (matrixX509ValidateCertInternal(pool, *subjectCert, ic, 1) < 0) {
- *valid = -1;
- return -1;
- }
-/*
- If any portion is invalid, it's all invalid
-*/
- if ((*subjectCert)->valid != 1) {
- *valid = -1;
- }
- *subjectCert = (*subjectCert)->next;
- }
- return 0;
-}
-
-/******************************************************************************/
-/*
- A signature validation for certificates. -1 return is an error. The success
- of the validation is returned in the 'valid' param of the subjectCert.
- 1 if the issuerCert signed the subject cert. -1 if not
-*/
-int32 matrixX509ValidateCert(psPool_t *pool, sslCert_t *subjectCert,
- sslCert_t *issuerCert, int32 *valid)
-{
- if (matrixX509ValidateCertInternal(pool, subjectCert, issuerCert, 0) < 0) {
- *valid = -1;
- return -1;
- }
- *valid = subjectCert->valid;
- return 0;
-}
-
-static int32 matrixX509ValidateCertInternal(psPool_t *pool,
- sslCert_t *subjectCert, sslCert_t *issuerCert, int32 chain)
-{
- sslCert_t *ic;
- unsigned char sigOut[10 + SSL_SHA1_HASH_SIZE + 5]; /* See below */
- int32 sigLen, sigType, rc;
-
- subjectCert->valid = -1;
-/*
- Supporting a one level chain or a self-signed cert. If the issuer
- is NULL, the self-signed test is done.
-*/
- if (issuerCert == NULL) {
- matrixStrDebugMsg("Warning: No CA to validate cert with\n", NULL);
- matrixStrDebugMsg("\tPerforming self-signed CA test\n", NULL);
- ic = subjectCert;
- } else {
- ic = issuerCert;
- }
-/*
- Path confirmation. If this is a chain verification, do not allow
- any holes in the path. Error out if issuer does not have CA permissions
- or if hashes do not match anywhere along the way.
-*/
- while (ic) {
- if (subjectCert != ic) {
-/*
- Certificate authority constraint only available in version 3 certs
-*/
- if ((ic->version > 1) && (ic->extensions.bc.ca <= 0)) {
- if (chain) {
- return -1;
- }
- ic = ic->next;
- continue;
- }
-/*
- Use sha1 hash of issuer fields computed at parse time to compare
-*/
- if (memcmp(subjectCert->issuer.hash, ic->subject.hash,
- SSL_SHA1_HASH_SIZE) != 0) {
- if (chain) {
- return -1;
- }
- ic = ic->next;
- continue;
- }
- }
-/*
- Signature confirmation
- The sigLen is the ASN.1 size in bytes for encoding the hash.
- The magic 10 is comprised of the SEQUENCE and ALGORITHM ID overhead.
- The magic 8 and 5 are the OID lengths of the corresponding algorithm.
- NOTE: if sigLen is modified, above sigOut static size must be changed
-*/
- if (subjectCert->sigAlgorithm == OID_RSA_MD5 ||
- subjectCert->sigAlgorithm == OID_RSA_MD2) {
- sigType = RSA_SIG;
- sigLen = 10 + SSL_MD5_HASH_SIZE + 8; /* See above */
- } else if (subjectCert->sigAlgorithm == OID_RSA_SHA1) {
- sigLen = 10 + SSL_SHA1_HASH_SIZE + 5; /* See above */
- sigType = RSA_SIG;
- } else {
- matrixStrDebugMsg("Unsupported signature algorithm\n", NULL);
- return -1;
- }
-
- if (sigType == RSA_SIG) {
- sslAssert(sigLen <= sizeof(sigOut));
-
- /* note: on error & no CA, flag as invalid, but don't exit as error here (<1.8.7? behavior) -- zzz */
- if (matrixRsaDecryptPub(pool, &(ic->publicKey),
- subjectCert->signature, subjectCert->signatureLen, sigOut,
- sigLen) < 0) {
- matrixStrDebugMsg("Unable to RSA decrypt signature\n", NULL);
- if (issuerCert) return -1;
- rc = -1;
- } else {
- rc = psAsnConfirmSignature(subjectCert->sigHash, sigOut, sigLen);
- }
- }
-/*
- If this is a chain test, fail on any gaps in the chain
-*/
- if (rc < 0) {
- if (chain) {
- return -1;
- }
- ic = ic->next;
- continue;
- }
-/*
- Fall through to here only if passed signature check.
-*/
- subjectCert->valid = 1;
- break;
- }
- return 0;
-}
-
-/******************************************************************************/
-/*
- Calls a user defined callback to allow for manual validation of the
- certificate.
-*/
-int32 matrixX509UserValidator(psPool_t *pool, sslCert_t *subjectCert,
- int32 (*certValidator)(sslCertInfo_t *t, void *arg), void *arg)
-{
- sslCertInfo_t *cert, *current, *next;
- int32 rc;
-
- if (certValidator == NULL) {
- return 0;
- }
-/*
- Pass the entire certificate chain to the user callback.
-*/
- current = cert = psMalloc(pool, sizeof(sslCertInfo_t));
- if (current == NULL) {
- return -8; /* SSL_MEM_ERROR */
- }
- memset(cert, 0x0, sizeof(sslCertInfo_t));
- while (subjectCert) {
-
- current->issuer.commonName = subjectCert->issuer.commonName;
- current->issuer.country = subjectCert->issuer.country;
- current->issuer.locality = subjectCert->issuer.locality;
- current->issuer.organization = subjectCert->issuer.organization;
- current->issuer.orgUnit = subjectCert->issuer.orgUnit;
- current->issuer.state = subjectCert->issuer.state;
-
- current->subject.commonName = subjectCert->subject.commonName;
- current->subject.country = subjectCert->subject.country;
- current->subject.locality = subjectCert->subject.locality;
- current->subject.organization = subjectCert->subject.organization;
- current->subject.orgUnit = subjectCert->subject.orgUnit;
- current->subject.state = subjectCert->subject.state;
-
- current->serialNumber = subjectCert->serialNumber;
- current->serialNumberLen = subjectCert->serialNumberLen;
- current->verified = subjectCert->valid;
- current->notBefore = subjectCert->notBefore;
- current->notAfter = subjectCert->notAfter;
-
- current->subjectAltName = subjectCert->extensions.san;
-
- if (subjectCert->certAlgorithm == OID_RSA_MD5 ||
- subjectCert->certAlgorithm == OID_RSA_MD2) {
- current->sigHashLen = SSL_MD5_HASH_SIZE;
- } else if (subjectCert->certAlgorithm == OID_RSA_SHA1) {
- current->sigHashLen = SSL_SHA1_HASH_SIZE;
- }
- current->sigHash = (char*)subjectCert->sigHash;
- if (subjectCert->next) {
- next = psMalloc(pool, sizeof(sslCertInfo_t));
- if (next == NULL) {
- while (cert) {
- next = cert->next;
- psFree(cert);
- cert = next;
- }
- return -8; /* SSL_MEM_ERROR */
- }
- memset(next, 0x0, sizeof(sslCertInfo_t));
- current->next = next;
- current = next;
- }
- subjectCert = subjectCert->next;
- }
-/*
- The user callback
-*/
- rc = certValidator(cert, arg);
-/*
- Free the chain
-*/
- while (cert) {
- next = cert->next;
- psFree(cert);
- cert = next;
- }
- return rc;
-}
-#endif /* USE_X509 */
-#endif /* USE_RSA */
-
-
-/******************************************************************************/
-
-