aboutsummaryrefslogtreecommitdiffstats
path: root/libparc/parc/security/parc_X509Certificate.c
diff options
context:
space:
mode:
Diffstat (limited to 'libparc/parc/security/parc_X509Certificate.c')
-rw-r--r--libparc/parc/security/parc_X509Certificate.c647
1 files changed, 0 insertions, 647 deletions
diff --git a/libparc/parc/security/parc_X509Certificate.c b/libparc/parc/security/parc_X509Certificate.c
deleted file mode 100644
index 2c964ae7..00000000
--- a/libparc/parc/security/parc_X509Certificate.c
+++ /dev/null
@@ -1,647 +0,0 @@
-/*
- * Copyright (c) 2017 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-/**
- * parc_X509Certificate.c
- * PARC Library
- */
-
-#include <config.h>
-
-#include <parc/security/parc_X509Certificate.h>
-#include <parc/security/parc_Certificate.h>
-
-#include <parc/security/parc_CryptoHash.h>
-#include <parc/security/parc_Security.h>
-#include <parc/algol/parc_Buffer.h>
-#include <parc/algol/parc_Object.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/security/parc_KeyType.h>
-
-#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/pem.h>
-#include <openssl/x509v3.h>
-#include <openssl/rand.h>
-#include <openssl/pkcs12.h>
-
-static PARCCryptoHash *_getPublicKeyDigest(void *interfaceContext);
-static PARCCryptoHash *_getCertificateDigest(void *interfaceContext);
-static PARCBuffer *_getDEREncodedCertificate(void *interfaceContext);
-static PARCBuffer *_getDEREncodedPublicKey(void *interfaceContext);
-static PARCCertificateType _getCertificateType(const void *cert);
-static PARCContainerEncoding _getContainerEncoding(const void *cert);
-
-PARCCertificateInterface *PARCX509CertificateInterface = &(PARCCertificateInterface) {
- .GetPublicKeyDigest = _getPublicKeyDigest,
- .GetCertificateDigest = _getCertificateDigest,
- .GetDEREncodedCertificate = _getDEREncodedCertificate,
- .GetDEREncodedPublicKey = _getDEREncodedPublicKey,
- .GetCertificateType = _getCertificateType,
- .GetContainerEncoding = _getContainerEncoding
-};
-
-struct parc_X509_certificate {
- PARCCertificateType type;
- PARCContainerEncoding encoding;
-
- // Cache of results
- PARCCryptoHash *keyDigest;
- PARCCryptoHash *certificateDigest;
- PARCBuffer *derEncodedCertificate;
- PARCBuffer *derEncodedKey;
-
- BIO *certificateBIO;
- X509 *certificate;
- EVP_PKEY *publicKey;
-};
-
-#ifdef __APPLE__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-static PARCCryptoHash *
-_getPublicKeyDigest(void *interfaceContext)
-{
- parcSecurity_AssertIsInitialized();
-
- parcAssertNotNull(interfaceContext, "Parameter must be non-null PARCX509Certificate");
-
- PARCX509Certificate *certificate = (PARCX509Certificate *) interfaceContext;
-
- if (certificate->keyDigest == NULL) {
- PARCBuffer *derEncodedKey = _getDEREncodedPublicKey(certificate);
- PARCCryptoHasher *hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256);
- parcCryptoHasher_Init(hasher);
- parcCryptoHasher_UpdateBuffer(hasher, derEncodedKey);
- PARCCryptoHash *hash = parcCryptoHasher_Finalize(hasher);
-
- certificate->keyDigest = parcCryptoHash_Create(PARCCryptoHashType_SHA256, parcCryptoHash_GetDigest(hash));
- parcCryptoHash_Release(&hash);
- parcCryptoHasher_Release(&hasher);
- }
-
- return certificate->keyDigest;
-}
-
-static PARCCryptoHash *
-_getCertificateDigest(void *interfaceContext)
-{
- parcSecurity_AssertIsInitialized();
-
- parcAssertNotNull(interfaceContext, "Parameter must be non-null PARCX509Certificate");
-
- PARCX509Certificate *certificate = (PARCX509Certificate *) interfaceContext;
-
- if (certificate->certificateDigest == NULL) {
- uint8_t digestBuffer[SHA256_DIGEST_LENGTH];
- int result = X509_digest(certificate->certificate, EVP_sha256(), digestBuffer, NULL);
- if (result) {
- PARCBuffer *digest =
- parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH, digestBuffer));
- certificate->certificateDigest = parcCryptoHash_Create(PARCCryptoHashType_SHA256, digest);
- parcBuffer_Release(&digest);
- }
- }
-
- return certificate->certificateDigest;
-}
-
-static PARCBuffer *
-_getDEREncodedCertificate(void *interfaceContext)
-{
- parcSecurity_AssertIsInitialized();
-
- parcAssertNotNull(interfaceContext, "Parameter must be non-null PARCX509Certificate");
-
- PARCX509Certificate *certificate = (PARCX509Certificate *) interfaceContext;
-
- if (certificate->derEncodedCertificate == NULL) {
- uint8_t *der = NULL;
-
- // this allocates memory for der
- int derLength = i2d_X509(certificate->certificate, &der);
- if (derLength > 0) {
- certificate->derEncodedCertificate =
- parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(derLength), derLength, der));
- }
- OPENSSL_free(der);
- }
-
- return certificate->derEncodedCertificate;
-}
-
-static PARCBuffer *
-_getDEREncodedPublicKey(void *interfaceContext)
-{
- parcSecurity_AssertIsInitialized();
-
- parcAssertNotNull(interfaceContext, "Parameter must be non-null PARCX509Certificate");
-
- PARCX509Certificate *certificate = (PARCX509Certificate *) interfaceContext;
-
- if (certificate->derEncodedKey == NULL) {
- uint8_t *der = NULL;
-
- // this allocates memory for der
- int derLength = i2d_PUBKEY(certificate->publicKey, &der);
- if (derLength > 0) {
- certificate->derEncodedKey = parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(derLength), derLength, der));
- }
- OPENSSL_free(der);
- }
-
- return certificate->derEncodedKey;
-}
-
-static PARCCertificateType
-_getCertificateType(const void *instance)
-{
- PARCX509Certificate *certificate = (PARCX509Certificate *) instance;
- return certificate->type;
-}
-
-static PARCContainerEncoding
-_getContainerEncoding(const void *instance)
-{
- PARCX509Certificate *certificate = (PARCX509Certificate *) instance;
- return certificate->encoding;
-}
-
-static void
-_parcX509Certificate_FinalRelease(PARCX509Certificate **certP)
-{
- PARCX509Certificate *cert = (PARCX509Certificate *) *certP;
- if (cert->certificateBIO != NULL) {
- BIO_free_all(cert->certificateBIO);
- }
- if (cert->publicKey != NULL) {
- EVP_PKEY_free(cert->publicKey);
- }
- if (cert->certificate != NULL) {
- X509_free(cert->certificate);
- }
- if (cert->keyDigest != NULL) {
- parcCryptoHash_Release(&cert->keyDigest);
- }
- if (cert->certificateDigest != NULL) {
- parcCryptoHash_Release(&cert->certificateDigest);
- }
- if (cert->derEncodedCertificate != NULL) {
- parcBuffer_Release(&cert->derEncodedCertificate);
- }
- if (cert->derEncodedKey != NULL) {
- parcBuffer_Release(&cert->derEncodedKey);
- }
-}
-
-parcObject_ExtendPARCObject(PARCX509Certificate, _parcX509Certificate_FinalRelease, NULL, NULL, NULL, NULL, NULL, NULL);
-
-static PARCX509Certificate *
-_createEmptyCertificate()
-{
- PARCX509Certificate *cert = parcObject_CreateInstance(PARCX509Certificate);
- cert->certificateBIO = NULL;
- cert->certificate = NULL;
- cert->publicKey = NULL;
- cert->keyDigest = NULL;
- cert->certificateDigest = NULL;
- cert->derEncodedCertificate = NULL;
- cert->derEncodedKey = NULL;
- parcAssertNotNull(cert, "Failure allocating memory for a new PARCX509Certificate instance");
-
- return cert;
-}
-
-static bool
-_addCertificateExtensionWithContext(X509 *cert, int nid, char *value)
-{
- X509_EXTENSION *extension;
- X509V3_CTX context;
-
- X509V3_set_ctx_nodb(&context);
- X509V3_set_ctx(&context, cert, cert, NULL, NULL, 0);
- extension = X509V3_EXT_conf_nid(NULL, &context, nid, value);
- if (extension == NULL) {
- return false;
- }
- X509_add_ext(cert, extension, -1);
- X509_EXTENSION_free(extension);
- return true;
-}
-
-static bool
-_addCertificateExtension(X509 *cert, int nid, char *value)
-{
- X509_EXTENSION *extension = X509V3_EXT_conf_nid(NULL, NULL, nid, value);
- if (extension == NULL) {
- return false;
- }
- X509_add_ext(cert, extension, -1);
- X509_EXTENSION_free(extension);
- return true;
-}
-
-static bool
-_addKeyIdentifier(X509 *cert)
-{
- unsigned char spkid[SHA256_DIGEST_LENGTH];
- char spkid_hex[1 + 2 * SHA256_DIGEST_LENGTH];
-
- /* Generate a KeyID which is the SHA256 digest of the DER encoding
- * of a SubjectPublicKeyInfo. Note that this is slightly uncommon,
- * but it is more general and complete than digesting the BIT STRING
- * component of the SubjectPublicKeyInfo itself (and no standard dictates
- * how you must generate a key ID). This code must produce the same result
- * as the Java version applied to the same SubjectPublicKeyInfo.
- */
-
- if (ASN1_item_digest(ASN1_ITEM_rptr(X509_PUBKEY), EVP_sha256(), X509_get_X509_PUBKEY(cert), spkid, NULL)) {
- for (int i = 0; i < 32; i++) {
- snprintf(&spkid_hex[2 * i], 3, "%02X", (unsigned) spkid[i]);
- }
- if (_addCertificateExtension(cert, NID_subject_key_identifier, spkid_hex) == true) {
- if (_addCertificateExtensionWithContext(cert, NID_authority_key_identifier, "keyid:always") == true) {
- return true;
- }
- }
- }
- return false;
-}
-
-static bool
-_addSubjectName(X509 *cert, const char *subjectname)
-{
- // Set up the simple subject name and issuer name for the certificate.
- X509_NAME *name = X509_get_subject_name(cert);
- parcAssertNotNull(name, "Got null name from X509_get_subject_name");
-
- if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *) subjectname, -1, -1, 0)) {
- if (X509_set_issuer_name(cert, name)) {
- return true;
- }
- }
- return false;
-}
-
-static bool
-_addRandomSerial(X509 *cert)
-{
- unsigned long serial = 0;
- unsigned char serial_bytes[sizeof(serial)];
-
- // Construct random positive serial number.
- RAND_bytes(serial_bytes, sizeof(serial_bytes));
- serial_bytes[0] &= 0x7F;
- serial = 0;
- for (int i = 0; i < sizeof(serial_bytes); i++) {
- serial = (256 * serial) + serial_bytes[i];
- }
- ASN1_INTEGER_set(X509_get_serialNumber(cert), serial);
- return true;
-}
-
-static bool
-_addValidityPeriod(X509 *cert, size_t validityDays)
-{
- // Set the validity from now for the specified number of days.
- X509_gmtime_adj(X509_get_notBefore(cert), (long) 0);
- X509_gmtime_adj(X509_get_notAfter(cert), (long) (60 * 60 * 24 * validityDays));
- return true;
-}
-
-static bool
-_addExtensions(X509 *cert)
-{
- // Add the necessary extensions.
- if (_addCertificateExtension(cert, NID_basic_constraints, "critical,CA:FALSE") == true) {
- if (_addCertificateExtension(cert, NID_key_usage, "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement") == true) {
- if (_addCertificateExtension(cert, NID_ext_key_usage, "clientAuth") == true) {
- return true;
- }
- }
- }
- return false;
-}
-
-static PARCX509Certificate *
-_parcX509Certificate_CreateFromPEMFile(const char *filename)
-{
- parcSecurity_AssertIsInitialized();
-
- PARCX509Certificate *cert = _createEmptyCertificate();
-
- FILE *fp = fopen(filename, "rb");
- if (fp == NULL) {
- parcX509Certificate_Release(&cert);
- return NULL;
- }
-
- cert->certificateBIO = BIO_new(BIO_s_file());
- size_t result = BIO_read_filename(cert->certificateBIO, filename);
- parcAssertTrue(result == 1, "Unable to open the specified file");
-
- cert->certificate = PEM_read_bio_X509(cert->certificateBIO, NULL, 0, NULL);
- cert->publicKey = X509_get_pubkey(cert->certificate);
-
- return cert;
-}
-
-parcObject_ImplementAcquire(parcX509Certificate, PARCX509Certificate);
-
-parcObject_ImplementRelease(parcX509Certificate, PARCX509Certificate);
-
-PARCX509Certificate *
-parcX509Certificate_CreateFromPEMFile(const char *filename)
-{
- PARCX509Certificate *certificate = _parcX509Certificate_CreateFromPEMFile(filename);
- if (certificate) {
- certificate->type = PARCCertificateType_X509;
- certificate->encoding = PARCContainerEncoding_PEM;
- return certificate;
- }
- return NULL;
-}
-
-PARCX509Certificate *
-parcX509Certificate_CreateFromDERBuffer(const PARCBuffer *buffer)
-{
- parcSecurity_AssertIsInitialized();
-
- PARCX509Certificate *cert = _createEmptyCertificate();
- cert->type = PARCCertificateType_X509;
- cert->encoding = PARCContainerEncoding_DER;
-
- PARCByteArray *array = parcBuffer_Array(buffer);
- uint8_t *arrayIn = parcByteArray_Array(array);
-
- cert->certificate = d2i_X509(&cert->certificate, (const unsigned char **) &arrayIn, parcBuffer_Remaining(buffer));
- if (cert->certificate == NULL) {
- parcX509Certificate_Release(&cert);
- return NULL;
- }
- cert->publicKey = X509_get_pubkey(cert->certificate);
-
- return cert;
-}
-
-PARCX509Certificate * _createSelfSignedCertificate_RSA(PARCBuffer **privateKeyBuffer, char *subjectName, int keyLength, size_t validityDays)
-{
- parcSecurity_AssertIsInitialized();
-
- RSA *rsa = RSA_new();
- parcAssertNotNull(rsa, "RSA_new failed.");
-
- EVP_PKEY *privateKey = EVP_PKEY_new();
- parcAssertNotNull(privateKey, "EVP_PKEY_new() failed.");
-
- X509 *cert = X509_new();
- parcAssertNotNull(cert, "X509_new() failed.");
-
- int res;
- BIGNUM *pub_exp;
-
- pub_exp = BN_new();
-
- BN_set_word(pub_exp, RSA_F4);
- res = 1;
- bool result = false;
- if (RSA_generate_key_ex(rsa, keyLength, pub_exp, NULL)) {
- if (EVP_PKEY_set1_RSA(privateKey, rsa)) {
- if (X509_set_version(cert, 2)) { // 2 => X509v3
- result = true;
- }
- }
- }
- if (result) {
- // add serial number
- if (_addRandomSerial(cert) == true) {
- if (_addValidityPeriod(cert, validityDays) == true) {
- if (X509_set_pubkey(cert, privateKey) == 1) {
- if (_addSubjectName(cert, subjectName) == true) {
- if (_addExtensions(cert) == true) {
- if (_addKeyIdentifier(cert) == true) {
- // The certificate is complete, sign it.
- if (X509_sign(cert, privateKey, EVP_sha256())) {
- result = true;
- } else {
- printf("error: (%d) %s\n", res, ERR_lib_error_string(res));
- }
- }
- }
- }
- }
- }
- }
- }
-
- ERR_print_errors_fp(stdout);
-
- BN_free(pub_exp);
-
- uint8_t *certificateDerEncoding = NULL;
- int numBytes = i2d_X509(cert, &certificateDerEncoding);
- if (numBytes < 0) {
- EVP_PKEY_free(privateKey);
- RSA_free(rsa);
- X509_free(cert);
-
- return NULL;
- }
-
- PARCBuffer *derBuffer = parcBuffer_Allocate(numBytes);
- parcBuffer_Flip(parcBuffer_PutArray(derBuffer, numBytes, certificateDerEncoding));
-
- PARCX509Certificate *certificate = parcX509Certificate_CreateFromDERBuffer(derBuffer);
- parcBuffer_Release(&derBuffer);
-
- uint8_t *privateKeyBytes = NULL;
- int privateKeyByteCount = i2d_PrivateKey(privateKey, &privateKeyBytes);
- if (privateKeyByteCount < 0) {
- EVP_PKEY_free(privateKey);
- RSA_free(rsa);
- X509_free(cert);
-
- return NULL;
- }
-
- *privateKeyBuffer = parcBuffer_Allocate(privateKeyByteCount);
- parcBuffer_Flip(parcBuffer_PutArray(*privateKeyBuffer, privateKeyByteCount, privateKeyBytes));
-
- EVP_PKEY_free(privateKey);
- RSA_free(rsa);
- X509_free(cert);
-
- return certificate;
-}
-
-static inline int _get_EC_params_from_lenght(int keyLength)
-{
- //For the moment only support 256bit key length
- switch (keyLength)
- {
- case 160:
- return NID_secp160k1;
- case 192:
- return NID_secp192k1;
- case 224:
- return NID_secp224k1;
- case 256:
- return NID_secp256k1;
- default:
- return -1;
- }
-
-}
-
-PARCX509Certificate * _createSelfSignedCertificate_EC(PARCBuffer **privateKeyBuffer, char *subjectName, int keyLength, size_t validityDays)
-{
- parcSecurity_AssertIsInitialized();
- int curve_params = _get_EC_params_from_lenght(keyLength);
- bool result = false;
-
- if (curve_params == -1)
- return NULL;
-
- EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve_params);
- parcAssertNotNull(ec_key, "EC key creation failed.");
-
- EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE);
-
- EVP_PKEY *pkey = EVP_PKEY_new();
- parcAssertNotNull(pkey, "EVP_PKEY_new() failed.");
-
- X509 *cert = X509_new();
- parcAssertNotNull(cert, "X509_new() failed.");
-
- int res;
-
-
- if((res = (EC_KEY_generate_key(ec_key))) < 0 )
- printf("error: (%d) %s\n", res, ERR_lib_error_string(res));
- else if((res = (EVP_PKEY_set1_EC_KEY(pkey, ec_key))) < 0 )
- printf("error: (%d) %s\n", res, ERR_lib_error_string(res));
- else if (X509_set_version(cert, 2)) { // 2 => X509v3
- result = true;
- }
-
- if (result) {
- // add serial number
- if (_addRandomSerial(cert) == true) {
- if (_addValidityPeriod(cert, validityDays) == true) {
- if (X509_set_pubkey(cert, pkey) == 1) {
- if (_addSubjectName(cert, subjectName) == true) {
- if (_addExtensions(cert) == true) {
- if (_addKeyIdentifier(cert) == true) {
- // The certificate is complete, sign it.
- if (X509_sign(cert, pkey, EVP_sha256())) {
- result = true;
- } else {
- printf("error: (%d) %s\n", res, ERR_lib_error_string(res));
- }
- }
- }
- }
- }
- }
- }
- }
-
- ERR_print_errors_fp(stdout);
-
-
-
- uint8_t *certificateDerEncoding = NULL;
- int numBytes = i2d_X509(cert, &certificateDerEncoding);
- if (numBytes < 0) {
- EVP_PKEY_free(pkey);
- EC_KEY_free(ec_key);
- X509_free(cert);
-
- return NULL;
- }
-
- PARCBuffer *derBuffer = parcBuffer_Allocate(numBytes);
- parcBuffer_Flip(parcBuffer_PutArray(derBuffer, numBytes, certificateDerEncoding));
-
- PARCX509Certificate *certificate = parcX509Certificate_CreateFromDERBuffer(derBuffer);
- parcBuffer_Release(&derBuffer);
-
- uint8_t *pkeyBytes = NULL;
- int pkeyByteCount = i2d_PrivateKey(pkey, &pkeyBytes);
- if (pkeyByteCount < 0) {
- EVP_PKEY_free(pkey);
- EC_KEY_free(ec_key);
- X509_free(cert);
-
- return NULL;
- }
-
- *privateKeyBuffer = parcBuffer_Allocate(pkeyByteCount);
- parcBuffer_Flip(parcBuffer_PutArray(*privateKeyBuffer, pkeyByteCount, pkeyBytes));
-
- EVP_PKEY_free(pkey);
- EC_KEY_free(ec_key);
- X509_free(cert);
-
- return certificate;
-}
-
-PARCX509Certificate *
-parcX509Certificate_CreateSelfSignedCertificate(PARCBuffer **privateKeyBuffer, char *subjectName, int keyLength, size_t validityDays, PARCKeyType keyType)
-{
- switch(keyType) {
- case PARCKeyType_RSA:
- return _createSelfSignedCertificate_RSA(privateKeyBuffer, subjectName, keyLength, validityDays);
- case PARCKeyType_EC:
- return _createSelfSignedCertificate_EC(privateKeyBuffer, subjectName, keyLength, validityDays);
- default:
- break;
- }
-
- return NULL;
-}
-
-
-PARCCryptoHash *
-parcX509Certificate_GetCertificateDigest(PARCX509Certificate *certificate)
-{
- return _getCertificateDigest(certificate);
-}
-
-PARCCryptoHash *
-parcX509Certificate_getPublicKeyDigest(PARCX509Certificate *certificate)
-{
- return _getPublicKeyDigest(certificate);
-}
-
-PARCBuffer *
-parcX509Certificate_GetDEREncodedCertificate(PARCX509Certificate *certificate)
-{
- return _getDEREncodedCertificate(certificate);
-}
-
-PARCBuffer *
-parcX509Certificate_GetDEREncodedPublicKey(PARCX509Certificate *certificate)
-{
- return _getDEREncodedPublicKey(certificate);
-}
-
-#ifdef __APPLE__
-#pragma clang diagnostic pop
-#endif
-