int write_default_fields( struct Certificate *certp) { struct CertificateToBeSigned *ctftbsp = &certp->toBeSigned; struct Extension *cextp; // key usage // If ca set keyCertSign and CRLsign bits // if ee set digitalSignature bit if (!(cextp = find_extension(&ctftbsp->extensions, id_keyUsage, false))) cextp = make_extension(&ctftbsp->extensions, id_keyUsage); if (eecert) { // clear everything first write_casn_num(&cextp->critical, 1); write_casn(&cextp->extnValue.keyUsage.self, (uchar *) "", 0); write_casn_bit(&cextp->extnValue.keyUsage.digitalSignature, 1); } else { write_casn_num(&cextp->critical, 1); write_casn(&cextp->extnValue.keyUsage.self, (uchar *) "", 0); write_casn_bit(&cextp->extnValue.keyUsage.keyCertSign, 1); write_casn_bit(&cextp->extnValue.keyUsage.cRLSign, 1); } // basic constraints // if ee no extension, if ca set ca to one cextp = find_extension(&ctftbsp->extensions, id_basicConstraints, false); if (eecert) { // no basic constraints extension for an ee cert if (cextp) removeExtension(&ctftbsp->extensions, id_basicConstraints); } else { int caConstraint = 1; if (!cextp) cextp = make_extension(&ctftbsp->extensions, id_basicConstraints); write_casn_num(&cextp->critical, 1); // write_casn(&cextp->extnValue.basicConstraints.self, (uchar *)"", // 0); write_casn_num(&cextp->extnValue.basicConstraints.cA, caConstraint); } return SUCCESS; }
int write_cert_aia( void *cert, void *val) { struct CertificateToBeSigned *tbsp = &((struct Certificate *)cert)->toBeSigned; struct Extension *extp; struct Extensions *extsp = &tbsp->extensions; struct AuthorityInfoAccessSyntax *aiasp; struct AccessDescription *accdsp; char *ptr = (char *)val; if (selfSigned) { // warn ignored return SUCCESS; } extp = make_extension(extsp, id_pkix_authorityInfoAccess); while (isspace((int)(unsigned char)*ptr)) ptr++; // strip leading spaces aiasp = &extp->extnValue.authorityInfoAccess; accdsp = (struct AccessDescription *)inject_casn(&aiasp->self, 0); write_objid(&accdsp->accessMethod, id_ad_caIssuers); write_casn(&accdsp->accessLocation.url, (unsigned char *)ptr, strlen(ptr)); return SUCCESS; }
/* * Take values from the subject keyfile and write them to the * current certificate. * val is filename of the subject keyfile * values of interest are the subject public key and the ski. */ int use_subject_keyfile( void *cert, void *val) { struct Certificate *certp = (struct Certificate *)cert; struct CertificateToBeSigned *ctftbsp = &certp->toBeSigned; struct SubjectPublicKeyInfo *spkinfop = &ctftbsp->subjectPublicKeyInfo; struct Extensions *extsp = &ctftbsp->extensions; struct Extension *extp; struct casn *spkp = &spkinfop->subjectPublicKey; if (val == NULL) return -1; // if no subjectPublicKey in the cert then get if from keyfile if (vsize_casn(&spkinfop->subjectPublicKey) <= 0) { write_objid(&spkinfop->algorithm.algorithm, id_rsadsi_rsaEncryption); write_casn(&spkinfop->algorithm.parameters.rsadsi_rsaEncryption, (uchar *) "", 0); if (!fillPublicKey(spkp, val)) return -1; } // always update SKI to match subjectPublicKey if (!(extp = find_extension(extsp, id_subjectKeyIdentifier, false))) extp = make_extension(extsp, id_subjectKeyIdentifier); writeHashedPublicKey(&extp->extnValue.subjectKeyIdentifier, spkp, false); return (SUCCESS); }
void Extensions::deserialize(TLS_Data_Reader& reader) { if(reader.has_remaining()) { const u16bit all_extn_size = reader.get_u16bit(); if(reader.remaining_bytes() != all_extn_size) throw Decoding_Error("Bad extension size"); while(reader.has_remaining()) { const u16bit extension_code = reader.get_u16bit(); const u16bit extension_size = reader.get_u16bit(); Extension* extn = make_extension(reader, extension_code, extension_size); if(extn) this->add(extn); else // unknown/unhandled extension reader.discard_next(extension_size); } } }
/* * Subject Information Access - comma separated ASCII strings */ int write_cert_sia( void *cert, void *val) { struct CertificateToBeSigned *tbsp = &((struct Certificate *)cert)->toBeSigned; struct Extension *extp; struct Extensions *extsp = &tbsp->extensions; struct SubjectInfoAccess *siap; struct AccessDescription *accdsp; char *ptr, *next; int numpts = 0, ptr_len; char token = ','; // FIXME - can have 3 object identifiers, have to parse out // r:, m: or s: for the different ones. // separate out the sia's and write each one into the sequence extp = make_extension(extsp, id_pe_subjectInfoAccess); ptr = val; while (ptr != NULL) { next = strchr(ptr, token); while (isspace((int)(unsigned char)*ptr)) ptr++; // strip leading spaces if (next == NULL) ptr_len = strlen(ptr); else { ptr_len = (char *)next - (char *)ptr; next++; } siap = &extp->extnValue.subjectInfoAccess; accdsp = (struct AccessDescription *)inject_casn(&siap->self, numpts++); if (!accdsp) return -1; // parse out what object id to use // s - signedOjbect, r - caRepository, m - manifest if (strncmp(ptr, "r:", strlen("r:")) == 0) write_objid(&accdsp->accessMethod, id_ad_caRepository); else if (strncmp(ptr, "s:", strlen("s:")) == 0) write_objid(&accdsp->accessMethod, id_ad_signedObject); else if (strncmp(ptr, "m:", strlen("m:")) == 0) write_objid(&accdsp->accessMethod, id_ad_rpkiManifest); else return -1; ptr += 2; // jump over the object id designation ptr_len -= 2; write_casn(&accdsp->accessLocation.url, (unsigned char *)ptr, ptr_len); ptr = next; } return SUCCESS; }
/* * Take values from the parents certificateand write them to the * current certificate. * val is filename of the parent certificate * fields of interest: * signature algorithm ID - overwrite (from template) * issuer - if filled in then don't overwrite * aki - use ski from issuer's cert * algorithm ID overwrite (from template) */ int use_parent_cert( void *cert, void *val) { struct Certificate issuer; struct Certificate *certp = (struct Certificate *)cert; struct CertificateToBeSigned *ctftbsp = &certp->toBeSigned; Certificate(&issuer, (ushort) 0); struct Extension *iextp, *cextp; // if not parent cert or we are self signed (and shouldn't have a parent // cert) if ((val == NULL) || (selfSigned)) return SUCCESS; // fprintf(stdout,"getting issuers cert %s\n", (char *)val); if (get_casn_file(&issuer.self, val, 0) < 0) { fprintf(stdout, "can't use issuers cert %s", (char *)val); return -1; } // copy algorithm identifiers (overwrite template value) // fprintf(stdout,"trying to copy algorithm identifiers\n"); copy_casn(&certp->algorithm.self, &issuer.toBeSigned.signature.self); copy_casn(&ctftbsp->signature.self, &issuer.toBeSigned.signature.self); // fprintf(stdout,"copied algorithm identifiers\n"); // copy subject name from issuer cert into issuer name in cert if issuer // name // not filled in. copy_casn(&ctftbsp->issuer.self, &issuer.toBeSigned.subject.self); // fprintf(stdout,"copied issuer name\n"); // replace aki extension of certificate with ski from issuer's cert cextp = find_extension(&ctftbsp->extensions, id_authKeyId, false); if (!cextp) cextp = make_extension(&ctftbsp->extensions, id_authKeyId); // fprintf(stdout,"copying ski as aki\n"); if ((iextp = find_extension(&issuer.toBeSigned.extensions, id_subjectKeyIdentifier, false))) { copy_casn(&cextp->extnValue.authKeyId.keyIdentifier, &iextp->extnValue.subjectKeyIdentifier); } else { fprintf(stdout, "Error: issuer cert has no SKI. AKI not set."); delete_casn(&issuer.self); return -1; } delete_casn(&issuer.self); return (SUCCESS); }
int write_cert_asnums( void *cert, void *val) { struct CertificateToBeSigned *tbsp = &((struct Certificate *)cert)->toBeSigned; struct Extension *extp; char *ptr, *next, *buf; int ptr_len; char token = ','; int num = 0; extp = make_extension(&tbsp->extensions, id_pe_autonomousSysNum); write_casn_num(&extp->critical, 1); struct ASNum *asNump = &extp->extnValue.autonomousSysNum; // if it is inherit - set that and done if (strncasecmp(val, "inherit", strlen("inherit")) == 0) { struct ASIdentifierChoiceA *asidChoice = &asNump->asnum; write_casn(&asidChoice->inherit, (uchar *) "", 0); return SUCCESS; } // go through all as numbers listed and add them to the block ptr = val; while (ptr != NULL) { next = strchr(ptr, token); while (isspace((int)(unsigned char)*ptr)) ptr++; // strip leading spaces if (next == NULL) ptr_len = strlen(ptr); else { ptr_len = (char *)next - (char *)ptr; next++; } if ((buf = strndup(ptr, ptr_len)) == NULL) return -1; if (write_ASNums(asNump, buf, num++) < 0) return -1; free(buf); ptr = next; } return SUCCESS; }
/* * Write the comma separated list of ascii strings into the CRL distribution * point extension */ int write_cert_crldp( void *cert, void *val) { struct CertificateToBeSigned *tbsp = &((struct Certificate *)cert)->toBeSigned; struct Extension *extp; struct Extensions *extsp = &tbsp->extensions; struct DistributionPoint *distp; struct GeneralName *gennamep; char *ptr, *next; int numpts = 0, ptr_len; char token = ','; if (selfSigned) { // warn ignored return SUCCESS; } // separate out the crldp's and write each one into the sequence extp = make_extension(extsp, id_cRLDistributionPoints); ptr = val; while (ptr != NULL) { next = strchr(ptr, token); while (isspace((int)(unsigned char)*ptr)) ptr++; // strip leading spaces if (next == NULL) ptr_len = strlen(ptr); else { ptr_len = (char *)next - (char *)ptr; next++; } distp = (struct DistributionPoint *)inject_casn(&extp->extnValue. cRLDistributionPoints.self, numpts++); if (!distp) return -1; gennamep = (struct GeneralName *)inject_casn(&distp->distributionPoint. fullName.self, 0); if (!gennamep) return -1; write_casn(&gennamep->url, (uchar *) ptr, ptr_len); ptr = next; } return SUCCESS; }
int write_key_identifier( struct Certificate *cert, char *id, char *val) { struct CertificateToBeSigned *tbsp = &((struct Certificate *)cert)->toBeSigned; int str_len, ki_len; char *str_ki = val; unsigned char *ki = NULL; int bytes_written; struct Extension *extp; struct Extensions *extsp = &tbsp->extensions; // strip off leading spaces and the 0x while (isspace((int)(unsigned char)*str_ki)) str_ki++; if (strncmp(str_ki, "0x", 2) != 0) return -1; str_ki += 2; str_len = strlen(str_ki); ki_len = (str_len + 1) / 2; ki = calloc(ki_len, sizeof(char)); if ((bytes_written = read_hex_val(str_ki, str_len, ki)) <= 0) { fprintf(stdout, "error converting key identifier (%s)\n", (char *)val); return -1; } // if it is there, clear it first extp = make_extension(extsp, id); if (strncmp(id, id_subjectKeyIdentifier, strlen(id_subjectKeyIdentifier)) == 0) { write_casn(&extp->extnValue.subjectKeyIdentifier, ki, bytes_written); free(ki); } else if (strncmp(id, id_authKeyId, strlen(id_authKeyId)) == 0) { write_casn(&extp->extnValue.authKeyId.keyIdentifier, ki, bytes_written); free(ki); } else return -1; return SUCCESS; }
int main( int argc, char *argv[]) { int delete_existing = 0; /* delete existing SIA access descriptions */ const char *file = NULL; /* certificate file */ struct Certificate cert; /* ASN.1 certificate object */ struct Extension *extp; /* ASN.1 X.509 extension pointer */ struct SubjectInfoAccess *siap; /* ASN.1 SIA pointer */ int c = 0; /* getopt option character */ int i; /* loop counter */ int ret; /* return value */ /* * Parse command line arguments. */ opterr = 0; while ((c = getopt(argc, argv, "dr:m:s:h")) != -1) { switch (c) { case 'd': delete_existing = 1; break; case 'r': /* id-ad-caRepository */ if (add_sia_request('r', optarg) != 0) { fprintf(stderr, "Error: failed to add URI request -r %s\n", optarg); return -1; } break; case 'm': /* id-ad-rpkiManifest */ if (add_sia_request('m', optarg) != 0) { fprintf(stderr, "Error: failed to add URI request -m %s\n", optarg); return -1; } break; case 's': /* id-ad-signedObject */ if (add_sia_request('s', optarg) != 0) { fprintf(stderr, "Error: failed to add URI request -s %s\n", optarg); return -1; } break; case 'h': usage(argc, argv); return -1; case '?': if (isprint(optopt)) fprintf(stderr, "Unknown option `-%c'.\n", optopt); else fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt); usage(argc, argv); return -1; default: usage(argc, argv); return -1; } } if (optind >= argc) { /* no arguments remain? */ usage(argc, argv); return -1; } file = argv[optind]; /* * Parse certificate. */ Certificate(&cert, (unsigned short)0); /* constructor */ ret = get_casn_file(&cert.self, (char *)file, 0); if (ret < 0) { fprintf(stderr, "Could not open file: %s\n", file); return -2; } /* * Find or create SIA extension. */ extp = find_extension(&cert.toBeSigned.extensions, id_pe_subjectInfoAccess, false); if (!extp) { extp = make_extension(&cert.toBeSigned.extensions, id_pe_subjectInfoAccess); if (!extp) { fprintf(stderr, "Could not create SIA extension.\n"); return -3; } } siap = &extp->extnValue.subjectInfoAccess; /* * Optionally delete existing AccessDescriptions. */ if (delete_existing) { clear_casn(&siap->self); /* This messes up the "DEFINED BY" * flag, so we need to set it again in * the next line. */ if (write_objid(&extp->extnID, id_pe_subjectInfoAccess) < 0) { fprintf(stderr, "Error clearing existing URIs.\n"); return -1; } } /* * For each AccessDescription request, insert it. */ for (i = 0; i < num_sia_requests; i++) { int current_size; struct AccessDescription *adp; /* ASN.1 AccessDescription pointer */ /* * Append new entry. */ current_size = num_items(&siap->self); adp = (struct AccessDescription *)inject_casn(&siap->self, current_size); if (!adp) { fprintf(stderr, "Error: failed to append access description.\n"); return -1; } if (write_objid(&adp->accessMethod, (char *)sia_requests[i].accessMethod) < 0) { fprintf(stderr, "Error: failed to set access method.\n"); return -1; } if (write_casn(&adp->accessLocation.url, (unsigned char *)sia_requests[i].accessLocation, strlen(sia_requests[i].accessLocation)) < 0) { fprintf(stderr, "Error: failed to set access location.\n"); return -1; } } /* * Check for non-empty SIA (RFC 5280) */ if (num_items(&siap->self) == 0) { fprintf(stderr, "SIA must have at least one AccessDescription, per RFC5280.\n"); return -1; } /* * Write to file. */ if (put_casn_file(&cert.self, (char *)file, 0) < 0) { fprintf(stderr, "Error: failed to write %s\n", file); return -4; } /* * Clean up. */ delete_casn(&cert.self); return 0; }
/* * ipv4 address are a comma separated list of either prefix or range * specifications for ipv4 addresses */ int write_cert_addrs( void *cert, void *val, int type) { struct CertificateToBeSigned *tbsp = &((struct Certificate *)cert)->toBeSigned; struct Extension *extp; struct Extensions *extsp = &tbsp->extensions; struct IPAddressFamilyA *famp; char *ptr, *next, *buf; int ptr_len; char token = ','; char family[2]; int num = 0; family[0] = 0; if (type == IPv4) family[1] = 1; else family[1] = 2; extp = find_extension(extsp, id_pe_ipAddrBlock, false); if (!extp) { extp = make_extension(extsp, id_pe_ipAddrBlock); write_casn_num(&extp->critical, 1); } if (type == IPv6) famp = (struct IPAddressFamilyA *)inject_casn(&extp->extnValue. ipAddressBlock.self, num_items(&extp->extnValue. ipAddressBlock. self)); else famp = (struct IPAddressFamilyA *)inject_casn(&extp->extnValue. ipAddressBlock.self, 0); write_casn(&famp->addressFamily, (unsigned char *)family, 2); // if it is inherit - set that and done if (strncmp(val, "inherit", strlen("inherit")) == 0) { struct IPAddressChoiceA *addrChoice = &famp->ipAddressChoice; write_casn(&addrChoice->inherit, (uchar *) "", 0); return SUCCESS; } // go through all addresses listed and add them to the block ptr = val; while (ptr != NULL) { next = strchr(ptr, token); while (isspace((int)(unsigned char)*ptr)) ptr++; // strip leading spaces if (next == NULL) ptr_len = strlen(ptr); else { ptr_len = (char *)next - (char *)ptr; next++; } if ((buf = strndup(ptr, ptr_len)) == NULL) return -1; if (write_family(famp, buf, num++) < 0) return -1; ptr = next; } return SUCCESS; }