Skip to content

Commit

Permalink
GNU TLS updates.
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelrsweet committed Oct 30, 2024
1 parent d1502ee commit 1925530
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 44 deletions.
1 change: 1 addition & 0 deletions cups/cups.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ extern http_t *cupsConnectDestBlock(cups_dest_t *dest, unsigned flags, int msec
# endif // __BLOCKS__
extern char *cupsCopyCredentials(const char *path, const char *common_name) _CUPS_PUBLIC;
extern char *cupsCopyCredentialsKey(const char *path, const char *common_name) _CUPS_PUBLIC;
extern char *cupsCopyCredentialsPublicKey(const char *path, const char *common_name) _CUPS_PUBLIC;
extern char *cupsCopyCredentialsRequest(const char *path, const char *common_name) _CUPS_PUBLIC;
extern int cupsCopyDest(cups_dest_t *dest, int num_dests, cups_dest_t **dests) _CUPS_PUBLIC;
extern int cupsCopyDestConflicts(http_t *http, cups_dest_t *dest, cups_dinfo_t *info, int num_options, cups_option_t *options, const char *new_option, const char *new_value, int *num_conflicts, cups_option_t **conflicts, int *num_resolved, cups_option_t **resolved) _CUPS_PUBLIC;
Expand Down
20 changes: 20 additions & 0 deletions cups/testcreds.c
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,16 @@ do_unit_tests(void)

if (data)
{
char *pubkey; // Public key

testBegin("cupsCopyCredentialsPublicKey()");
if ((pubkey = cupsCopyCredentialsPublicKey(TEST_CERT_PATH, "altprinter")) != NULL)
testEnd(true);
else
testEndMessage(false, "%s", cupsGetErrorString());

free(pubkey);

testBegin("cupsSignCredentialsRequest(altprinter w/alt names)");
if (cupsSignCredentialsRequest(TEST_CERT_PATH, "altprinter", data, "_site_", CUPS_CREDPURPOSE_ALL, CUPS_CREDUSAGE_ALL, /*cb*/NULL, /*cb_data*/NULL, time(NULL) + 30 * 86400))
{
Expand Down Expand Up @@ -500,6 +510,16 @@ do_unit_tests(void)

if (data)
{
char *pubkey; // Public key

testBegin("cupsCopyCredentialsPublicKey()");
if ((pubkey = cupsCopyCredentialsPublicKey(TEST_CERT_PATH, "altprinter")) != NULL)
testEnd(true);
else
testEndMessage(false, "%s", cupsGetErrorString());

free(pubkey);

testBegin("cupsSignCredentialsRequest(altprinter w/o alt names)");
if (cupsSignCredentialsRequest(TEST_CERT_PATH, "altprinter", data, "_site_", CUPS_CREDPURPOSE_ALL, CUPS_CREDUSAGE_ALL, /*cb*/NULL, /*cb_data*/NULL, time(NULL) + 30 * 86400))
{
Expand Down
158 changes: 118 additions & 40 deletions cups/tls-gnutls.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,13 @@ cupsCreateCredentials(
bool ret = false; // Return value
gnutls_x509_crt_t crt = NULL; // New certificate
gnutls_x509_privkey_t key = NULL; // Encryption private key
gnutls_pubkey_t pubkey = NULL; // Encryption public key
gnutls_x509_crt_t root_crt = NULL;// Root certificate
gnutls_x509_privkey_t root_key = NULL;// Root private key
char defpath[1024], // Default path
crtfile[1024], // Certificate filename
keyfile[1024], // Private key filename
pubfile[1024], // Public key filename
*root_crtdata, // Root certificate data
*root_keydata; // Root private key data
unsigned gnutls_usage = 0;// GNU TLS keyUsage bits
Expand All @@ -208,6 +210,27 @@ cupsCreateCredentials(

http_make_path(crtfile, sizeof(crtfile), path, common_name, "crt");
http_make_path(keyfile, sizeof(keyfile), path, common_name, "key");
http_make_path(pubfile, sizeof(pubfile), path, common_name, "pub");

// Key usage flags...
if (usage & CUPS_CREDUSAGE_DIGITAL_SIGNATURE)
gnutls_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
if (usage & CUPS_CREDUSAGE_NON_REPUDIATION)
gnutls_usage |= GNUTLS_KEY_NON_REPUDIATION;
if (usage & CUPS_CREDUSAGE_KEY_ENCIPHERMENT)
gnutls_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
if (usage & CUPS_CREDUSAGE_DATA_ENCIPHERMENT)
gnutls_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
if (usage & CUPS_CREDUSAGE_KEY_AGREEMENT)
gnutls_usage |= GNUTLS_KEY_KEY_AGREEMENT;
if (usage & CUPS_CREDUSAGE_KEY_CERT_SIGN)
gnutls_usage |= GNUTLS_KEY_KEY_CERT_SIGN;
if (usage & CUPS_CREDUSAGE_CRL_SIGN)
gnutls_usage |= GNUTLS_KEY_CRL_SIGN;
if (usage & CUPS_CREDUSAGE_ENCIPHER_ONLY)
gnutls_usage |= GNUTLS_KEY_ENCIPHER_ONLY;
if (usage & CUPS_CREDUSAGE_DECIPHER_ONLY)
gnutls_usage |= GNUTLS_KEY_DECIPHER_ONLY;

// Create the encryption key...
DEBUG_puts("1cupsCreateCredentials: Creating key pair.");
Expand Down Expand Up @@ -238,6 +261,39 @@ cupsCreateCredentials(
goto done;
}

bytes = sizeof(buffer);

if ((err = gnutls_pubkey_init(&pubkey)) < 0)
{
DEBUG_printf("1cupsCreateCredentials: Unable to create public key: %s", gnutls_strerror(err));
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, gnutls_strerror(err), 0);
goto done;
}
else if ((err = gnutls_pubkey_import_privkey(pubkey, key, gnutls_usage, /*flags*/0)) < 0)
{
DEBUG_printf("1cupsCreateCredentials: Unable to import public key: %s", gnutls_strerror(err));
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, gnutls_strerror(err), 0);
goto done;
}
else if ((err = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_PEM, buffer, &bytes)) < 0)
{
DEBUG_printf("1cupsCreateCredentials: Unable to export public key: %s", gnutls_strerror(err));
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, gnutls_strerror(err), 0);
goto done;
}
else if ((fp = cupsFileOpen(pubfile, "w")) != NULL)
{
DEBUG_printf("1cupsCreateCredentials: Writing public key to \"%s\".", keyfile);
cupsFileWrite(fp, (char *)buffer, bytes);
cupsFileClose(fp);
}
else
{
DEBUG_printf("1cupsCreateCredentials: Unable to create public key file \"%s\": %s", keyfile, strerror(errno));
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
goto done;
}

// Create the certificate...
DEBUG_puts("1cupsCreateCredentials: Generating X.509 certificate.");

Expand Down Expand Up @@ -310,25 +366,6 @@ cupsCreateCredentials(
if (purpose & CUPS_CREDPURPOSE_OCSP_SIGNING)
gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_OCSP_SIGNING, 0);

if (usage & CUPS_CREDUSAGE_DIGITAL_SIGNATURE)
gnutls_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
if (usage & CUPS_CREDUSAGE_NON_REPUDIATION)
gnutls_usage |= GNUTLS_KEY_NON_REPUDIATION;
if (usage & CUPS_CREDUSAGE_KEY_ENCIPHERMENT)
gnutls_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
if (usage & CUPS_CREDUSAGE_DATA_ENCIPHERMENT)
gnutls_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
if (usage & CUPS_CREDUSAGE_KEY_AGREEMENT)
gnutls_usage |= GNUTLS_KEY_KEY_AGREEMENT;
if (usage & CUPS_CREDUSAGE_KEY_CERT_SIGN)
gnutls_usage |= GNUTLS_KEY_KEY_CERT_SIGN;
if (usage & CUPS_CREDUSAGE_CRL_SIGN)
gnutls_usage |= GNUTLS_KEY_CRL_SIGN;
if (usage & CUPS_CREDUSAGE_ENCIPHER_ONLY)
gnutls_usage |= GNUTLS_KEY_ENCIPHER_ONLY;
if (usage & CUPS_CREDUSAGE_DECIPHER_ONLY)
gnutls_usage |= GNUTLS_KEY_DECIPHER_ONLY;

gnutls_x509_crt_set_key_usage(crt, gnutls_usage);
gnutls_x509_crt_set_version(crt, 3);

Expand Down Expand Up @@ -423,6 +460,8 @@ cupsCreateCredentials(
gnutls_x509_crt_deinit(crt);
if (key)
gnutls_x509_privkey_deinit(key);
if (pubkey)
gnutls_pubkey_deinit(pubkey);

return (ret);
}
Expand Down Expand Up @@ -502,9 +541,11 @@ cupsCreateCredentialsRequest(
bool ret = false; // Return value
gnutls_x509_crq_t crq = NULL; // Certificate request
gnutls_x509_privkey_t key = NULL; // Private/public key pair
gnutls_pubkey_t pubkey = NULL; // Encryption public key
char defpath[1024], // Default path
csrfile[1024], // Certificate signing request filename
keyfile[1024]; // Private key filename
keyfile[1024], // Private key filename
pubfile[1024]; // Public key filename
unsigned gnutls_usage = 0;// GNU TLS keyUsage bits
cups_file_t *fp; // Key/cert file
unsigned char buffer[8192]; // Buffer for key/cert data
Expand All @@ -526,6 +567,27 @@ cupsCreateCredentialsRequest(

http_make_path(csrfile, sizeof(csrfile), path, common_name, "csr");
http_make_path(keyfile, sizeof(keyfile), path, common_name, "ktm");
http_make_path(pubfile, sizeof(pubfile), path, common_name, "pub");

// Key usage flags...
if (usage & CUPS_CREDUSAGE_DIGITAL_SIGNATURE)
gnutls_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
if (usage & CUPS_CREDUSAGE_NON_REPUDIATION)
gnutls_usage |= GNUTLS_KEY_NON_REPUDIATION;
if (usage & CUPS_CREDUSAGE_KEY_ENCIPHERMENT)
gnutls_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
if (usage & CUPS_CREDUSAGE_DATA_ENCIPHERMENT)
gnutls_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
if (usage & CUPS_CREDUSAGE_KEY_AGREEMENT)
gnutls_usage |= GNUTLS_KEY_KEY_AGREEMENT;
if (usage & CUPS_CREDUSAGE_KEY_CERT_SIGN)
gnutls_usage |= GNUTLS_KEY_KEY_CERT_SIGN;
if (usage & CUPS_CREDUSAGE_CRL_SIGN)
gnutls_usage |= GNUTLS_KEY_CRL_SIGN;
if (usage & CUPS_CREDUSAGE_ENCIPHER_ONLY)
gnutls_usage |= GNUTLS_KEY_ENCIPHER_ONLY;
if (usage & CUPS_CREDUSAGE_DECIPHER_ONLY)
gnutls_usage |= GNUTLS_KEY_DECIPHER_ONLY;

// Create the encryption key...
DEBUG_puts("1cupsCreateCredentialsRequest: Creating key pair.");
Expand Down Expand Up @@ -555,7 +617,40 @@ cupsCreateCredentialsRequest(
goto done;
}

// Create the certificate...
bytes = sizeof(buffer);

if ((err = gnutls_pubkey_init(&pubkey)) < 0)
{
DEBUG_printf("1cupsCreateCredentials: Unable to create public key: %s", gnutls_strerror(err));
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, gnutls_strerror(err), 0);
goto done;
}
else if ((err = gnutls_pubkey_import_privkey(pubkey, key, gnutls_usage, /*flags*/0)) < 0)
{
DEBUG_printf("1cupsCreateCredentials: Unable to import public key: %s", gnutls_strerror(err));
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, gnutls_strerror(err), 0);
goto done;
}
else if ((err = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_PEM, buffer, &bytes)) < 0)
{
DEBUG_printf("1cupsCreateCredentials: Unable to export public key: %s", gnutls_strerror(err));
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, gnutls_strerror(err), 0);
goto done;
}
else if ((fp = cupsFileOpen(pubfile, "w")) != NULL)
{
DEBUG_printf("1cupsCreateCredentials: Writing public key to \"%s\".", keyfile);
cupsFileWrite(fp, (char *)buffer, bytes);
cupsFileClose(fp);
}
else
{
DEBUG_printf("1cupsCreateCredentials: Unable to create public key file \"%s\": %s", keyfile, strerror(errno));
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
goto done;
}

// Create the certificate signing request...
DEBUG_puts("1cupsCreateCredentialsRequest: Generating X.509 certificate request.");

if (!organization)
Expand Down Expand Up @@ -613,25 +708,6 @@ cupsCreateCredentialsRequest(
if (purpose & CUPS_CREDPURPOSE_OCSP_SIGNING)
gnutls_x509_crq_set_key_purpose_oid(crq, GNUTLS_KP_OCSP_SIGNING, 0);

if (usage & CUPS_CREDUSAGE_DIGITAL_SIGNATURE)
gnutls_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
if (usage & CUPS_CREDUSAGE_NON_REPUDIATION)
gnutls_usage |= GNUTLS_KEY_NON_REPUDIATION;
if (usage & CUPS_CREDUSAGE_KEY_ENCIPHERMENT)
gnutls_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
if (usage & CUPS_CREDUSAGE_DATA_ENCIPHERMENT)
gnutls_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
if (usage & CUPS_CREDUSAGE_KEY_AGREEMENT)
gnutls_usage |= GNUTLS_KEY_KEY_AGREEMENT;
if (usage & CUPS_CREDUSAGE_KEY_CERT_SIGN)
gnutls_usage |= GNUTLS_KEY_KEY_CERT_SIGN;
if (usage & CUPS_CREDUSAGE_CRL_SIGN)
gnutls_usage |= GNUTLS_KEY_CRL_SIGN;
if (usage & CUPS_CREDUSAGE_ENCIPHER_ONLY)
gnutls_usage |= GNUTLS_KEY_ENCIPHER_ONLY;
if (usage & CUPS_CREDUSAGE_DECIPHER_ONLY)
gnutls_usage |= GNUTLS_KEY_DECIPHER_ONLY;

gnutls_x509_crq_set_key_usage(crq, gnutls_usage);
gnutls_x509_crq_set_version(crq, 3);

Expand Down Expand Up @@ -669,6 +745,8 @@ cupsCreateCredentialsRequest(
gnutls_x509_crq_deinit(crq);
if (key)
gnutls_x509_privkey_deinit(key);
if (pubkey)
gnutls_pubkey_deinit(pubkey);

return (ret);
}
Expand Down
40 changes: 37 additions & 3 deletions cups/tls-openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ cupsCreateCredentials(
char defpath[1024], // Default path
crtfile[1024], // Certificate filename
keyfile[1024], // Private key filename
pubfile[1024], // Public key filename
root_crtfile[1024], // Root certificate filename
root_keyfile[1024]; // Root private key filename
time_t curtime; // Current time
Expand Down Expand Up @@ -235,7 +236,7 @@ cupsCreateCredentials(
X509_set_notBefore(cert, notBefore);
ASN1_TIME_free(notBefore);

notAfter = ASN1_TIME_new();
notAfter = ASN1_TIME_new();
ASN1_TIME_set(notAfter, expiration_date);
X509_set_notAfter(cert, notAfter);
ASN1_TIME_free(notAfter);
Expand Down Expand Up @@ -358,6 +359,7 @@ cupsCreateCredentials(
// Save them...
http_make_path(crtfile, sizeof(crtfile), path, common_name, "crt");
http_make_path(keyfile, sizeof(keyfile), path, common_name, "key");
http_make_path(pubfile, sizeof(pubfile), path, common_name, "pub");

if ((bio = BIO_new_file(keyfile, "wb")) == NULL)
{
Expand All @@ -374,6 +376,21 @@ cupsCreateCredentials(

BIO_free(bio);

if ((bio = BIO_new_file(pubfile, "wb")) == NULL)
{
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
goto done;
}

if (!PEM_write_bio_PUBKEY(bio, pkey))
{
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to write public key."), true);
BIO_free(bio);
goto done;
}

BIO_free(bio);

if ((bio = BIO_new_file(crtfile, "wb")) == NULL)
{
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
Expand Down Expand Up @@ -490,7 +507,8 @@ cupsCreateCredentialsRequest(
char temp[1024], // Temporary directory name
*tempptr, // Pointer into temporary string
csrfile[1024], // Certificate signing request filename
keyfile[1024]; // Private key filename
keyfile[1024], // Private key filename
pubfile[1024]; // Public key filename
STACK_OF(X509_EXTENSION) *exts; // Extensions
unsigned i; // Looping var
cups_credpurpose_t purpose_bit; // Current purpose
Expand All @@ -511,6 +529,7 @@ cupsCreateCredentialsRequest(

http_make_path(csrfile, sizeof(csrfile), path, common_name, "csr");
http_make_path(keyfile, sizeof(keyfile), path, common_name, "ktm");
http_make_path(pubfile, sizeof(pubfile), path, common_name, "pub");

// Create the encryption key...
DEBUG_puts("1cupsCreateCredentialsRequest: Creating key pair.");
Expand Down Expand Up @@ -593,6 +612,21 @@ cupsCreateCredentialsRequest(

BIO_free(bio);

if ((bio = BIO_new_file(pubfile, "wb")) == NULL)
{
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
goto done;
}

if (!PEM_write_bio_PUBKEY(bio, pkey))
{
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to write public key."), true);
BIO_free(bio);
goto done;
}

BIO_free(bio);

if ((bio = BIO_new_file(csrfile, "wb")) == NULL)
{
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
Expand Down Expand Up @@ -996,7 +1030,7 @@ cupsSignCredentialsRequest(
ASN1_INTEGER *serial; // Serial number
ASN1_TIME *notBefore, // Initial date
*notAfter; // Expiration date
BIO *bio; // Output file
BIO *bio; // Input/output file
char temp[1024]; // Temporary string
int i, j, // Looping vars
num_exts; // Number of extensions
Expand Down
15 changes: 14 additions & 1 deletion cups/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,24 @@ cupsCopyCredentialsKey(
}


//
// 'cupsCopyCredentialsPublicKey()' - Copy the public key for a X.509 certificate request.
//

char * // O - PEM-encoded public key
cupsCopyCredentialsPublicKey(
const char *path, // I - Directory path for certificate/key store or `NULL` for default
const char *common_name) // I - Common name
{
return (http_copy_file(path, common_name, "pub"));
}


//
// 'cupsCopyCredentialsRequest()' - Copy the X.509 certificate signing request to a string.
//

char *
char * // O - PEM-encoded X.509 certificate signing request
cupsCopyCredentialsRequest(
const char *path, // I - Directory path for certificate/key store or `NULL` for default
const char *common_name) // I - Common name
Expand Down

0 comments on commit 1925530

Please sign in to comment.