void calculate_rsa_ckaid(osw_public_key *pub) { if(pub->alg == PUBKEY_ALG_RSA) { struct RSA_public_key *rsa = &pub->u.rsa; if(rsa->key_rfc3110.len == 0) { /* key has no 3110 representation, need to cons up one */ unsigned int e_size = mpz_sizeinbase(&rsa->e, 256); unsigned int key3110len = rsa->k + 1 + e_size; rsa->key_rfc3110.ptr = alloc_bytes(key3110len, "rfc3110 format of public key [created]"); rsa->key_rfc3110.len = key3110len; unsigned char *here = rsa->key_rfc3110.ptr; here[0] = e_size; here++; mpz_export(here, NULL, 1, 1, 1, 0, &rsa->e); here += e_size; mpz_export(here, NULL, 1, 1, 1, 0, &rsa->n); } /* maybe #ifdef SHA2 ? */ /* calculate the hash of the public key, using SHA-2 */ sha256_hash_buffer(rsa->key_rfc3110.ptr, rsa->key_rfc3110.len, pub->key_ckaid, sizeof(pub->key_ckaid)); datatot(pub->key_ckaid, sizeof(pub->key_ckaid), 'G', pub->key_ckaid_print_buf, sizeof(pub->key_ckaid_print_buf)); } }
/* * check if any crls are about to expire */ void check_crls(void) { x509crl_t *crl; lock_crl_list("check_crls"); crl = x509crls; while (crl != NULL) { deltatime_t time_left = realtimediff(crl->nextUpdate, realnow()); char buf[ASN1_BUF_LEN]; DBG(DBG_X509, { dntoa(buf, ASN1_BUF_LEN, crl->issuer); DBG_log("issuer: '%s'", buf); if (crl->authKeyID.ptr != NULL) { datatot(crl->authKeyID.ptr, crl->authKeyID.len, ':', buf, ASN1_BUF_LEN); DBG_log("authkey: %s", buf); } DBG_log("%ld seconds left", (long)deltasecs(time_left)); }); if (deltaless(time_left, deltatimescale(2, 1, crl_check_interval))) add_crl_fetch_request(crl->issuer, crl->distributionPoints); crl = crl->next; }
/* * check if any crls are about to expire */ void check_crls(void) { #ifdef HAVE_THREADS x509crl_t *crl; time_t current_time = time(NULL); lock_crl_list("check_crls"); crl = x509crls; while (crl != NULL) { time_t time_left = crl->nextUpdate - current_time; u_char buf[ASN1_BUF_LEN]; DBG(DBG_X509, dntoa(buf, ASN1_BUF_LEN, crl->issuer); DBG_log("issuer: '%s'",buf); if (crl->authKeyID.ptr != NULL) { datatot(crl->authKeyID.ptr, crl->authKeyID.len, ':' , buf, ASN1_BUF_LEN); DBG_log("authkey: %s", buf); } DBG_log("%ld seconds left", time_left) ) if (time_left < 2*crl_check_interval) add_crl_fetch_request(crl->issuer, crl->distributionPoints); crl = crl->next; } unlock_crl_list("check_crls"); #endif }
/* generate a transaction id as the MD5 hash of an public key * the transaction id is also used as a unique serial number */ void scep_generate_transaction_id(const RSA_public_key_t *rsak , chunk_t *transID, chunk_t *serialNumber) { char buf[MD5_DIGEST_SIZE]; chunk_t digest = { buf, sizeof(buf) }; chunk_t public_key = pkcs1_build_publicKeyInfo(rsak); bool msb_set; u_char *pos; compute_digest(public_key, OID_MD5, &digest); pfree(public_key.ptr); /* is the most significant bit of the digest set? */ msb_set = (*digest.ptr & 0x80) == 0x80; /* allocate space for the serialNumber */ serialNumber->len = msb_set + digest.len; serialNumber->ptr = alloc_bytes(serialNumber->len, "serialNumber"); /* the serial number as the two's complement of the digest */ pos = serialNumber->ptr; if (msb_set) { *pos++ = 0x00; } memcpy(pos, digest.ptr, digest.len); /* the transaction id is the serial number in hex format */ transID->len = 2*digest.len; transID->ptr = alloc_bytes(transID->len + 1, "transID"); datatot(digest.ptr, digest.len, 16, transID->ptr, transID->len + 1); }
/* * check if an ocsp status is about to expire */ void check_ocsp(void) { ocsp_location_t *location; lock_ocsp_cache("check_ocsp"); location = ocsp_cache; while (location != NULL) { char buf[BUF_LEN]; bool first = TRUE; ocsp_certinfo_t *certinfo = location->certinfo; while (certinfo != NULL) { if (!certinfo->once) { time_t time_left = certinfo->nextUpdate - time(NULL); DBG(DBG_CONTROL, if (first) { dntoa(buf, BUF_LEN, location->issuer); DBG_log("issuer: '%s'", buf); if (location->authKeyID.ptr != NULL) { datatot(location->authKeyID.ptr, location->authKeyID.len , ':', buf, BUF_LEN); DBG_log("authkey: %s", buf); } first = FALSE; } datatot(certinfo->serialNumber.ptr, certinfo->serialNumber.len , ':', buf, BUF_LEN); DBG_log("serial: %s, %ld seconds left", buf, time_left) ) #ifdef HAVE_THREADS if (time_left < 2*crl_check_interval) add_ocsp_fetch_request(location, certinfo->serialNumber); #endif } certinfo = certinfo->next; } location = location->next; }
/* converts a binary request to base64 with 64 characters per line * newline and '+' characters are escaped by %0A and %2B, respectively */ static char* escape_http_request(chunk_t req) { char *escaped_req = NULL; char *p1, *p2; int lines = 0; int plus = 0; int n = 0; /* compute and allocate the size of the base64-encoded request */ int len = 1 + 4*((req.len + 2)/3); char *encoded_req = alloc_bytes(len, "encoded request"); /* do the base64 conversion */ len = datatot(req.ptr, req.len, 64, encoded_req, len); /* compute newline characters to be inserted every 64 characters */ lines = (len - 2) / 64; /* count number of + characters to be escaped */ p1 = encoded_req; while (*p1 != '\0') { if (*p1++ == '+') plus++; } escaped_req = alloc_bytes(len + 3*(lines + plus), "escaped request"); /* escape special characters in the request */ p1 = encoded_req; p2 = escaped_req; while (*p1 != '\0') { if (n == 64) { memcpy(p2, "%0A", 3); p2 += 3; n = 0; } if (*p1 == '+') { memcpy(p2, "%2B", 3); p2 += 3; } else { *p2++ = *p1; } p1++; n++; } *p2 = '\0'; pfreeany(encoded_req); return escaped_req; }
static void print(struct private_key_stuff *pks, int count, struct id *id, bool disclose) { char idb[IDTOA_BUF] = "n/a"; if (id) { idtoa(id, idb, IDTOA_BUF); } char pskbuf[128] = ""; if (pks->kind == PPK_PSK || pks->kind == PPK_XAUTH) { datatot(pks->u.preshared_secret.ptr, pks->u.preshared_secret.len, 'x', pskbuf, sizeof(pskbuf)); } if (count) { /* ipsec.secrets format */ printf("%d(%d): ", pks->line, count); } else { /* NSS format */ printf("<%2d> ", pks->line); } switch (pks->kind) { case PPK_PSK: printf("PSK keyid: %s\n", idb); if (disclose) printf(" psk: \"%s\"\n", pskbuf); break; case PPK_RSA: { printf("RSA"); char *keyid = pks->u.RSA_private_key.pub.keyid; printf(" keyid: %s", keyid[0] ? keyid : "<missing-pubkey>"); if (id) { printf(" id: %s", idb); } char *ckaid = ckaid_as_string(pks->u.RSA_private_key.pub.ckaid); printf(" ckaid: %s\n", ckaid); pfree(ckaid); break; } case PPK_XAUTH: printf("XAUTH keyid: %s\n", idb); if (disclose) printf(" xauth: \"%s\"\n", pskbuf); break; case PPK_NULL: /* can't happen but the compiler does not know that */ printf("NULL authentication -- cannot happen: %s\n", idb); abort(); } }
/* generates a unique fingerprint of the pkcs10 request * by computing an MD5 hash over it */ void scep_generate_pkcs10_fingerprint(chunk_t pkcs10, chunk_t *fingerprint) { char buf[MD5_DIGEST_SIZE]; chunk_t digest = { buf, sizeof(buf) }; /* the fingerprint is the MD5 hash in hexadecimal format */ compute_digest(pkcs10, OID_MD5, &digest); fingerprint->len = 2*digest.len; fingerprint->ptr = alloc_bytes(fingerprint->len + 1, "fingerprint"); datatot(digest.ptr, digest.len, 16, fingerprint->ptr, fingerprint->len + 1); }
int print_key(struct secret *secret , struct private_key_stuff *pks , void *uservoid, bool disclose) { int lineno = osw_get_secretlineno(secret); struct id_list *l = osw_get_idlist(secret); char idb[IDTOA_BUF]; int count=1; char pskbuf[128]; if(pks->kind == PPK_PSK || pks->kind==PPK_XAUTH) { datatot(pks->u.preshared_secret.ptr, pks->u.preshared_secret.len, 'x', pskbuf, sizeof(pskbuf)); } while(l) { idtoa(&l->id, idb, IDTOA_BUF); switch(pks->kind) { case PPK_PSK: printf("%d(%d): PSK keyid: %s\n", lineno, count, idb); if(disclose) printf(" psk: \"%s\"\n", pskbuf); break; case PPK_RSA: printf("%d(%d): RSA keyid: %s with id: %s\n", lineno, count, pks->u.RSA_private_key.pub.keyid,idb); break; case PPK_XAUTH: printf("%d(%d): XAUTH keyid: %s\n", lineno, count, idb); if(disclose) printf(" xauth: \"%s\"\n", pskbuf); break; case PPK_PIN: printf("%d:(%d) PIN key-type not yet supported for id: %s\n", lineno, count, idb); break; } l=l->next; count++; } return 1; }
/* - conv - convert bits to output in specified datatot format * NOTE: result points into a STATIC buffer */ static const char *conv(const unsigned char *bits, size_t nbytes, int format) { static char convbuf[MAXBITS / 4 + 50]; /* enough for hex */ size_t n; n = datatot(bits, nbytes, format, convbuf, sizeof(convbuf)); if (n == 0) { fprintf(stderr, "%s: can't-happen convert error\n", me); exit(1); } if (n > sizeof(convbuf)) { fprintf(stderr, "%s: can't-happen convert overflow (need %d)\n", me, (int) n); exit(1); } return convbuf; }
/** * Generate a transaction id as the MD5 hash of an public key * the transaction id is also used as a unique serial number */ void scep_generate_transaction_id(public_key_t *key, chunk_t *transID, chunk_t *serialNumber) { chunk_t digest = chunk_alloca(HASH_SIZE_MD5); chunk_t keyEncoding = chunk_empty, keyInfo; hasher_t *hasher; bool msb_set; u_char *pos; key->get_encoding(key, KEY_PUB_ASN1_DER, &keyEncoding); keyInfo = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_algorithmIdentifier(OID_RSA_ENCRYPTION), asn1_bitstring("m", keyEncoding)); hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); hasher->get_hash(hasher, keyInfo, digest.ptr); hasher->destroy(hasher); free(keyInfo.ptr); /* is the most significant bit of the digest set? */ msb_set = (*digest.ptr & 0x80) == 0x80; /* allocate space for the serialNumber */ serialNumber->len = msb_set + digest.len; serialNumber->ptr = malloc(serialNumber->len); /* the serial number as the two's complement of the digest */ pos = serialNumber->ptr; if (msb_set) { *pos++ = 0x00; } memcpy(pos, digest.ptr, digest.len); /* the transaction id is the serial number in hex format */ transID->len = 2*digest.len; transID->ptr = malloc(transID->len + 1); datatot(digest.ptr, digest.len, 16, transID->ptr, transID->len + 1); }
/* * generate an RSA signature key * * e is fixed at 3, without discussion. That would not be wise if these * keys were to be used for encryption, but for signatures there are some * real speed advantages. * See also: https://www.imperialviolet.org/2012/03/16/rsae.html */ void rsasigkey(int nbits, int seedbits, const struct lsw_conf_options *oco) { PK11RSAGenParams rsaparams = { nbits, (long) F4 }; PK11SlotInfo *slot = NULL; SECKEYPrivateKey *privkey = NULL; SECKEYPublicKey *pubkey = NULL; realtime_t now = realnow(); lsw_nss_buf_t err; if (!lsw_nss_setup(oco->nssdir, 0, lsw_nss_get_password, err)) { fprintf(stderr, "%s: %s\n", progname, err); exit(1); } #ifdef FIPS_CHECK if (PK11_IsFIPS() && !FIPSCHECK_verify(NULL, NULL)) { fprintf(stderr, "FIPS HMAC integrity verification test failed.\n"); exit(1); } #endif /* Good for now but someone may want to use a hardware token */ slot = lsw_nss_get_authenticated_slot(err); if (slot == NULL) { fprintf(stderr, "%s: %s\n", progname, err); lsw_nss_shutdown(); exit(1); } /* Do some random-number initialization. */ UpdateNSS_RNG(seedbits); privkey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaparams, &pubkey, PR_TRUE, PK11_IsFIPS() ? PR_TRUE : PR_FALSE, lsw_return_nss_password_file_info()); /* inTheToken, isSensitive, passwordCallbackFunction */ if (privkey == NULL) { fprintf(stderr, "%s: key pair generation failed: \"%d\"\n", progname, PORT_GetError()); return; } chunk_t public_modulus = { .ptr = pubkey->u.rsa.modulus.data, .len = pubkey->u.rsa.modulus.len, }; chunk_t public_exponent = { .ptr = pubkey->u.rsa.publicExponent.data, .len = pubkey->u.rsa.publicExponent.len, }; char *hex_ckaid; { SECItem *ckaid = PK11_GetLowLevelKeyIDForPrivateKey(privkey); if (ckaid == NULL) { fprintf(stderr, "%s: 'CKAID' calculation failed\n", progname); exit(1); } hex_ckaid = strdup(conv(ckaid->data, ckaid->len, 16)); SECITEM_FreeItem(ckaid, PR_TRUE); } /*privkey->wincx = &pwdata;*/ PORT_Assert(pubkey != NULL); fprintf(stderr, "Generated RSA key pair with CKAID %s was stored in the NSS database\n", hex_ckaid); /* and the output */ libreswan_log("output...\n"); /* deliberate extra newline */ printf("\t# RSA %d bits %s %s", nbits, outputhostname, ctime(&now.rt.tv_sec)); /* ctime provides \n */ printf("\t# for signatures only, UNSAFE FOR ENCRYPTION\n"); printf("\t#ckaid=%s\n", hex_ckaid); /* RFC2537/RFC3110-ish format */ { char *base64 = NULL; err_t err = rsa_pubkey_to_base64(public_exponent, public_modulus, &base64); if (err) { fprintf(stderr, "%s: unexpected error encoding RSA public key '%s'\n", progname, err); exit(1); } printf("\t#pubkey=%s\n", base64); pfree(base64); } printf("\tModulus: 0x%s\n", conv(public_modulus.ptr, public_modulus.len, 16)); printf("\tPublicExponent: 0x%s\n", conv(public_exponent.ptr, public_exponent.len, 16)); if (hex_ckaid != NULL) free(hex_ckaid); if (privkey != NULL) SECKEY_DestroyPrivateKey(privkey); if (pubkey != NULL) SECKEY_DestroyPublicKey(pubkey); lsw_nss_shutdown(); } /* * lsw_random - get some random bytes from /dev/random (or wherever) * NOTE: This is only used for additional seeding of the NSS RNG */ void lsw_random(size_t nbytes, unsigned char *buf) { size_t ndone; int dev; ssize_t got; dev = open(device, 0); if (dev < 0) { fprintf(stderr, "%s: could not open %s (%s)\n", progname, device, strerror(errno)); exit(1); } ndone = 0; libreswan_log("getting %d random seed bytes for NSS from %s...\n", (int) nbytes * BITS_PER_BYTE, device); while (ndone < nbytes) { got = read(dev, buf + ndone, nbytes - ndone); if (got < 0) { fprintf(stderr, "%s: read error on %s (%s)\n", progname, device, strerror(errno)); exit(1); } if (got == 0) { fprintf(stderr, "%s: eof on %s!?!\n", progname, device); exit(1); } ndone += got; } close(dev); } /* - conv - convert bits to output in specified datatot format * NOTE: result points into a STATIC buffer */ static const char *conv(const unsigned char *bits, size_t nbytes, int format) { static char convbuf[MAXBITS / 4 + 50]; /* enough for hex */ size_t n; n = datatot(bits, nbytes, format, convbuf, sizeof(convbuf)); if (n == 0) { fprintf(stderr, "%s: can't-happen convert error\n", progname); exit(1); } if (n > sizeof(convbuf)) { fprintf(stderr, "%s: can't-happen convert overflow (need %d)\n", progname, (int) n); exit(1); } return convbuf; }
/* * Converts a binary key ID into hexadecimal format */ static int keyidtoa(char *dst, size_t dstlen, chunk_t keyid) { int n = datatot(keyid.ptr, keyid.len, 'x', dst, dstlen); return ((n < (int)dstlen)? n : (int)dstlen) - 1; }
/* * generate an RSA signature key * * e is fixed at 3, without discussion. That would not be wise if these * keys were to be used for encryption, but for signatures there are some * real speed advantages. * See also: https://www.imperialviolet.org/2012/03/16/rsae.html */ void rsasigkey(int nbits, int seedbits, char *configdir, char *password) { SECStatus rv; PK11RSAGenParams rsaparams = { nbits, (long) E }; secuPWData pwdata = { PW_NONE, NULL }; PK11SlotInfo *slot = NULL; SECKEYPrivateKey *privkey = NULL; SECKEYPublicKey *pubkey = NULL; realtime_t now = realnow(); if (password == NULL) { pwdata.source = PW_NONE; } else { /* check if passwd == configdir/nsspassword */ size_t cdl = strlen(configdir); size_t pwl = strlen(password); static const char suf[] = "/nsspassword"; if (pwl == cdl + sizeof(suf) - 1 && memeq(password, configdir, cdl) && memeq(password + cdl, suf, sizeof(suf))) pwdata.source = PW_FROMFILE; else pwdata.source = PW_PLAINTEXT; } pwdata.data = password; lsw_nss_buf_t err; if (!lsw_nss_setup(configdir, FALSE/*rw*/, GetModulePassword, err)) { fprintf(stderr, "%s: %s\n", me, err); exit(1); } #ifdef FIPS_CHECK if (PK11_IsFIPS() && !FIPSCHECK_verify(NULL, NULL)) { fprintf(stderr, "FIPS HMAC integrity verification test failed.\n"); exit(1); } #endif if (PK11_IsFIPS() && password == NULL) { fprintf(stderr, "%s: On FIPS mode a password is required\n", me); exit(1); } /* Good for now but someone may want to use a hardware token */ slot = PK11_GetInternalKeySlot(); /* In which case this may be better */ /* slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN, password ? &pwdata : NULL); */ /* or the user may specify the name of a token. */ #if 0 if (PK11_IsFIPS() || !PK11_IsInternal(slot)) { rv = PK11_Authenticate(slot, PR_FALSE, &pwdata); if (rv != SECSuccess) { fprintf(stderr, "%s: could not authenticate to token '%s'\n", me, PK11_GetTokenName(slot)); return; } } #endif /* 0 */ /* Do some random-number initialization. */ UpdateNSS_RNG(seedbits); /* Log in to the token */ if (password != NULL) { rv = PK11_Authenticate(slot, PR_FALSE, &pwdata); if (rv != SECSuccess) { fprintf(stderr, "%s: could not authenticate to token '%s'\n", me, PK11_GetTokenName(slot)); return; } } privkey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaparams, &pubkey, PR_TRUE, password != NULL? PR_TRUE : PR_FALSE, &pwdata); /* inTheToken, isSensitive, passwordCallbackFunction */ if (privkey == NULL) { fprintf(stderr, "%s: key pair generation failed: \"%d\"\n", me, PORT_GetError()); return; } chunk_t public_modulus = { .ptr = pubkey->u.rsa.modulus.data, .len = pubkey->u.rsa.modulus.len, }; chunk_t public_exponent = { .ptr = pubkey->u.rsa.publicExponent.data, .len = pubkey->u.rsa.publicExponent.len, }; char *hex_ckaid; { SECItem *ckaid = PK11_GetLowLevelKeyIDForPrivateKey(privkey); if (ckaid == NULL) { fprintf(stderr, "%s: 'CKAID' calculation failed\n", me); exit(1); } hex_ckaid = strdup(conv(ckaid->data, ckaid->len, 16)); SECITEM_FreeItem(ckaid, PR_TRUE); } /*privkey->wincx = &pwdata;*/ PORT_Assert(pubkey != NULL); fprintf(stderr, "Generated RSA key pair with CKAID %s was stored in the NSS database\n", hex_ckaid); /* and the output */ report("output...\n"); /* deliberate extra newline */ printf("\t# RSA %d bits %s %s", nbits, outputhostname, ctime(&now.real_secs)); /* ctime provides \n */ printf("\t# for signatures only, UNSAFE FOR ENCRYPTION\n"); printf("\t#ckaid=%s\n", hex_ckaid); /* RFC2537/RFC3110-ish format */ { char *bundle = base64_bundle(E, public_modulus); printf("\t#pubkey=%s\n", bundle); pfree(bundle); } printf("\tModulus: 0x%s\n", conv(public_modulus.ptr, public_modulus.len, 16)); printf("\tPublicExponent: 0x%s\n", conv(public_exponent.ptr, public_exponent.len, 16)); if (hex_ckaid != NULL) free(hex_ckaid); if (privkey != NULL) SECKEY_DestroyPrivateKey(privkey); if (pubkey != NULL) SECKEY_DestroyPublicKey(pubkey); lsw_nss_shutdown(LSW_NSS_CLEANUP); } /* * getrandom - get some random bytes from /dev/random (or wherever) * NOTE: This is only used for additional seeding of the NSS RNG */ void getrandom(size_t nbytes, unsigned char *buf) { size_t ndone; int dev; ssize_t got; dev = open(device, 0); if (dev < 0) { fprintf(stderr, "%s: could not open %s (%s)\n", me, device, strerror(errno)); exit(1); } ndone = 0; if (verbose) { fprintf(stderr, "getting %d random seed bytes for NSS from %s...\n", (int) nbytes * BITS_PER_BYTE, device); } while (ndone < nbytes) { got = read(dev, buf + ndone, nbytes - ndone); if (got < 0) { fprintf(stderr, "%s: read error on %s (%s)\n", me, device, strerror(errno)); exit(1); } if (got == 0) { fprintf(stderr, "%s: eof on %s!?!\n", me, device); exit(1); } ndone += got; } close(dev); } /* - conv - convert bits to output in specified datatot format * NOTE: result points into a STATIC buffer */ static const char *conv(const unsigned char *bits, size_t nbytes, int format) { static char convbuf[MAXBITS / 4 + 50]; /* enough for hex */ size_t n; n = datatot(bits, nbytes, format, convbuf, sizeof(convbuf)); if (n == 0) { fprintf(stderr, "%s: can't-happen convert error\n", me); exit(1); } if (n > sizeof(convbuf)) { fprintf(stderr, "%s: can't-happen convert overflow (need %d)\n", me, (int) n); exit(1); } return convbuf; } /* - report - report progress, if indicated */ void report(msg) char *msg; { if (!verbose) return; fprintf(stderr, "%s\n", msg); }
/* x509.c SEAM */ static void list_x509cert_chain(const char *caption, x509cert_t* cert, u_char auth_flags , bool utc) { bool first = TRUE; time_t tnow; /* determine the current time */ time(&tnow); while (cert != NULL) { if (auth_flags == AUTH_NONE || (auth_flags & cert->authority_flags)) { unsigned keysize; char keyid[KEYID_BUF]; char buf[ASN1_BUF_LEN]; char tbuf[TIMETOA_BUF]; cert_t c; c.type = CERT_X509_SIGNATURE; c.u.x509 = cert; if (first) { DBG_log( " "); DBG_log( "List of X.509 %s Certificates:", caption); DBG_log( " "); first = FALSE; } DBG_log( "NOW, count: %d", cert->count); dntoa(buf, ASN1_BUF_LEN, cert->subject); DBG_log( " subject: '%s'", buf); dntoa(buf, ASN1_BUF_LEN, cert->issuer); DBG_log( " issuer: '%s'", buf); datatot(cert->serialNumber.ptr, cert->serialNumber.len, ':' , buf, ASN1_BUF_LEN); DBG_log( " serial: %s", buf); form_keyid(cert->publicExponent, cert->modulus, keyid, &keysize); DBG_log( " pubkey: %4d RSA Key %s" , 8*keysize, keyid); DBG_log( " validity: not before %s %s", timetoa(&cert->notBefore, utc, tbuf, sizeof(tbuf)), (cert->notBefore < tnow)?"ok":"fatal (not valid yet)"); DBG_log( " not after %s %s", timetoa(&cert->notAfter, utc, tbuf, sizeof(tbuf)), check_expiry(cert->notAfter, CA_CERT_WARNING_INTERVAL, TRUE)); if (cert->subjectKeyID.ptr != NULL) { datatot(cert->subjectKeyID.ptr, cert->subjectKeyID.len, ':' , buf, ASN1_BUF_LEN); DBG_log( " subjkey: %s", buf); } if (cert->authKeyID.ptr != NULL) { datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':' , buf, ASN1_BUF_LEN); DBG_log( " authkey: %s", buf); } if (cert->authKeySerialNumber.ptr != NULL) { datatot(cert->authKeySerialNumber.ptr, cert->authKeySerialNumber.len , ':', buf, ASN1_BUF_LEN); DBG_log( " aserial: %s", buf); } } cert = cert->next; } }
/* establish trust into a candidate authcert by going up the trust chain. * validity and revocation status are not checked. */ bool trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain) { int pathlen; lock_authcert_list("trust_authcert_candidate"); for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) { const x509cert_t *authcert = NULL; DBG(DBG_CONTROL, char buf[ASN1_BUF_LEN]; dntoa(buf, ASN1_BUF_LEN, cert->subject); DBG_log("subject: '%s'",buf); dntoa(buf, ASN1_BUF_LEN, cert->issuer); DBG_log("issuer: '%s'",buf); if (cert->authKeyID.ptr != NULL) { datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':' , buf, ASN1_BUF_LEN); DBG_log("authkey: %s", buf); } ); /* search in alternative chain first */ authcert = get_alt_cacert(cert->issuer, cert->authKeySerialNumber , cert->authKeyID, alt_chain); if (authcert != NULL) { DBG(DBG_CONTROL, DBG_log("issuer cacert found in alternative chain") ) } else { /* search in trusted chain */ authcert = get_authcert(cert->issuer, cert->authKeySerialNumber , cert->authKeyID, AUTH_CA); if (authcert != NULL) { DBG(DBG_CONTROL, DBG_log("issuer cacert found") ) } else { plog("issuer cacert not found"); unlock_authcert_list("trust_authcert_candidate"); return FALSE; } } if (!check_signature(cert->tbsCertificate, cert->signature, cert->algorithm, authcert)) { plog("invalid certificate signature"); unlock_authcert_list("trust_authcert_candidate"); return FALSE; } DBG(DBG_CONTROL, DBG_log("valid certificate signature") ) /* check if cert is a self-signed root ca */ if (pathlen > 0 && same_dn(cert->issuer, cert->subject)) { DBG(DBG_CONTROL, DBG_log("reached self-signed root ca") ) unlock_authcert_list("trust_authcert_candidate"); return TRUE; } /* go up one step in the trust chain */ cert = authcert; }