/* 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 sslRsaCert_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, ¤tCA) < 0) { 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; }
void matrixSslFreeKeys(sslKeys_t *keys) { matrixRsaFreeKeys(keys); }
/* 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 matrixRsaReadKeysEx(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 sslRsaCert_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 = matrixRsaReadPrivKey(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; }