static int _parcPkcs12KeyStore_ParseFile(PARCPkcs12KeyStore *keystore, const char *filename, const char *password) { parcSecurity_AssertIsInitialized(); FILE *fp = fopen(filename, "rb"); assertNotNull(fp, "Error opening %s: %s", filename, strerror(errno)); if (fp == NULL) { return -1; } PKCS12 *p12Keystore = NULL; d2i_PKCS12_fp(fp, &p12Keystore); fclose(fp); int success = PKCS12_parse(p12Keystore, password, &keystore->private_key, &keystore->x509_cert, NULL); PKCS12_free(p12Keystore); if (!success) { unsigned long errcode; while ((errcode = ERR_get_error()) != 0) { fprintf(stderr, "openssl error: %s\n", ERR_error_string(errcode, NULL)); } return -1; } keystore->public_key = X509_get_pubkey(keystore->x509_cert); return 0; }
LONGBOW_TEST_CASE(Global, parcSecurity_IsInitialized) { parcSecurity_Init(); parcSecurity_AssertIsInitialized(); parcSecurity_Fini(); assertFalse(parcSecurity_IsInitialized(), "parcSecurity_IsInitialized should be false now"); }
static PARCSignature * _SignDigest(PARCPublicKeySigner *signer, const PARCCryptoHash *digestToSign) { parcSecurity_AssertIsInitialized(); assertNotNull(signer, "Parameter must be non-null CCNxFileKeystore"); assertNotNull(digestToSign, "Buffer to sign must not be null"); // TODO: what is the best way to expose this? PARCKeyStore *keyStore = signer->keyStore; PARCBuffer *privateKeyBuffer = parcKeyStore_GetDEREncodedPrivateKey(keyStore); EVP_PKEY *privateKey = NULL; size_t keySize = parcBuffer_Remaining(privateKeyBuffer); uint8_t *bytes = parcBuffer_Overlay(privateKeyBuffer, keySize); privateKey = d2i_PrivateKey(EVP_PKEY_RSA, &privateKey, (const unsigned char **) &bytes, keySize); parcBuffer_Release(&privateKeyBuffer); RSA *rsa = EVP_PKEY_get1_RSA(privateKey); int opensslDigestType; switch (parcCryptoHash_GetDigestType(digestToSign)) { case PARCCryptoHashType_SHA256: opensslDigestType = NID_sha256; break; case PARCCryptoHashType_SHA512: opensslDigestType = NID_sha512; break; default: trapUnexpectedState("Unknown digest type: %s", parcCryptoHashType_ToString(parcCryptoHash_GetDigestType(digestToSign))); } uint8_t *sig = parcMemory_Allocate(RSA_size(rsa)); assertNotNull(sig, "parcMemory_Allocate(%u) returned NULL", RSA_size(rsa)); unsigned sigLength = 0; PARCBuffer *bb_digest = parcCryptoHash_GetDigest(digestToSign); int result = RSA_sign(opensslDigestType, (unsigned char *) parcByteArray_Array(parcBuffer_Array(bb_digest)), (int) parcBuffer_Remaining(bb_digest), sig, &sigLength, rsa); assertTrue(result == 1, "Got error from RSA_sign: %d", result); RSA_free(rsa); PARCBuffer *bbSign = parcBuffer_Allocate(sigLength); parcBuffer_Flip(parcBuffer_PutArray(bbSign, sigLength, sig)); parcMemory_Deallocate((void **) &sig); PARCSignature *signature = parcSignature_Create(_GetSigningAlgorithm(signer), parcCryptoHash_GetDigestType(digestToSign), bbSign ); parcBuffer_Release(&bbSign); return signature; }
static PARCCryptoHash * _GetCertificateDigest(PARCPkcs12KeyStore *keystore) { parcSecurity_AssertIsInitialized(); assertNotNull(keystore, "Parameter must be non-null PARCPkcs12KeyStore"); if (keystore->certificate_digest == NULL) { uint8_t digestBuffer[SHA256_DIGEST_LENGTH]; int result = X509_digest(keystore->x509_cert, EVP_sha256(), digestBuffer, NULL); if (result) { keystore->certificate_digest = parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH, digestBuffer)); } } PARCCryptoHash *hash = parcCryptoHash_Create(PARC_HASH_SHA256, keystore->certificate_digest); return hash; }
static PARCCryptoHash * _GetPublickKeyDigest(PARCPkcs12KeyStore *keystore) { parcSecurity_AssertIsInitialized(); assertNotNull(keystore, "Parameter must be non-null PARCPkcs12KeyStore"); if (keystore->public_key_digest == NULL) { AUTHORITY_KEYID *akid = X509_get_ext_d2i(keystore->x509_cert, NID_authority_key_identifier, NULL, NULL); if (akid != NULL) { ASN1_OCTET_STRING *skid = X509_get_ext_d2i(keystore->x509_cert, NID_subject_key_identifier, NULL, NULL); if (skid != NULL) { keystore->public_key_digest = parcBuffer_PutArray(parcBuffer_Allocate(skid->length), skid->length, skid->data); parcBuffer_Flip(keystore->public_key_digest); ASN1_OCTET_STRING_free(skid); } AUTHORITY_KEYID_free(akid); } } // If we could not load the digest from the certificate, then calculate it from the public key. if (keystore->public_key_digest == NULL) { uint8_t digestBuffer[SHA256_DIGEST_LENGTH]; int result = ASN1_item_digest(ASN1_ITEM_rptr(X509_PUBKEY), EVP_sha256(), X509_get_X509_PUBKEY(keystore->x509_cert), digestBuffer, NULL); if (result != 1) { assertTrue(0, "Could not compute digest over certificate public key"); } else { keystore->public_key_digest = parcBuffer_PutArray(parcBuffer_Allocate(SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH, digestBuffer); parcBuffer_Flip(keystore->public_key_digest); } } // This stores a reference, so keystore->public_key_digest will remain valid // even if the cryptoHasher is destroyed return parcCryptoHash_Create(PARC_HASH_SHA256, keystore->public_key_digest); }
static PARCBuffer * _GetDEREncodedPrivateKey(PARCPkcs12KeyStore *keystore) { parcSecurity_AssertIsInitialized(); assertNotNull(keystore, "Parameter must be non-null PARCPkcs12KeyStore"); if (keystore->private_key_der == NULL) { uint8_t *der = NULL; // this allocates memory for der int derLength = i2d_PrivateKey(keystore->private_key, &der); if (derLength > 0) { keystore->private_key_der = parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(derLength), derLength, der)); } OPENSSL_free(der); } return parcBuffer_Copy(keystore->private_key_der); }
// ============================================================= LONGBOW_STOP_DEPRECATED_WARNINGS // ============================================================= bool parcPkcs12KeyStore_CreateFile( const char *filename, const char *password, const char *subjectName, unsigned keyLength, unsigned validityDays) { parcSecurity_AssertIsInitialized(); bool result = false; PARCCertificateFactory *factory = parcCertificateFactory_Create(PARCCertificateType_X509, PARCContainerEncoding_DER); PARCBuffer *privateKeyBuffer; PARCCertificate *certificate = parcCertificateFactory_CreateSelfSignedCertificate(factory, &privateKeyBuffer, (char *) subjectName, keyLength, validityDays); parcCertificateFactory_Release(&factory); if (certificate != NULL) { // construct the full PKCS12 keystore to hold the certificate and private key // Extract the private key EVP_PKEY *privateKey = NULL; uint8_t *privateKeyBytes = parcBuffer_Overlay(privateKeyBuffer, parcBuffer_Limit(privateKeyBuffer)); d2i_PrivateKey(EVP_PKEY_RSA, &privateKey, (const unsigned char **) &privateKeyBytes, parcBuffer_Limit(privateKeyBuffer)); parcBuffer_Release(&privateKeyBuffer); // Extract the certificate PARCBuffer *certBuffer = parcCertificate_GetDEREncodedCertificate(certificate); uint8_t *certBytes = parcBuffer_Overlay(certBuffer, parcBuffer_Limit(certBuffer)); X509 *cert = NULL; d2i_X509(&cert, (const unsigned char **) &certBytes, parcBuffer_Limit(certBuffer)); parcCertificate_Release(&certificate); PKCS12 *pkcs12 = PKCS12_create((char *) password, "ccnxuser", privateKey, cert, NULL, 0, 0, 0 /*default iter*/, PKCS12_DEFAULT_ITER /*mac_iter*/, 0); if (pkcs12 != NULL) { int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0600); if (fd != -1) { FILE *fp = fdopen(fd, "wb"); if (fp != NULL) { i2d_PKCS12_fp(fp, pkcs12); fclose(fp); result = true; } else { trapUnrecoverableState("Cannot fdopen(3) the file descriptor %d", fd); } close(fd); } else { trapUnrecoverableState("Cannot open(2) the file '%s': %s", filename, strerror(errno)); } PKCS12_free(pkcs12); X509_free(cert); EVP_PKEY_free(privateKey); } else { unsigned long errcode; while ((errcode = ERR_get_error()) != 0) { fprintf(stderr, "openssl error: %s\n", ERR_error_string(errcode, NULL)); } trapUnrecoverableState("PKCS12_create returned a NULL value."); } } return result; }
LONGBOW_TEST_CASE(Global, parcSecurity_Init) { parcSecurity_Init(); parcSecurity_AssertIsInitialized(); parcSecurity_Fini(); }