📄 ca.c
字号:
"at the same time"); return EINVAL; } if (tbs->flags.proxy) { if (tbs->san.len > 0) { hx509_set_error_string(context, 0, EINVAL, "Proxy certificate is not allowed " "to have SubjectAltNames"); return EINVAL; } } /* version [0] Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, */ tbsc->version = calloc(1, sizeof(*tbsc->version)); if (tbsc->version == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } *tbsc->version = rfc3280_version_3; /* serialNumber CertificateSerialNumber, */ if (tbs->flags.serial) { ret = der_copy_heim_integer(&tbs->serial, &tbsc->serialNumber); if (ret) { hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } } else { tbsc->serialNumber.length = 20; tbsc->serialNumber.data = malloc(tbsc->serialNumber.length); if (tbsc->serialNumber.data == NULL){ ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } /* XXX diffrent */ RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length); ((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f; } /* signature AlgorithmIdentifier, */ ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to copy sigature alg"); goto out; } /* issuer Name, */ if (issuername) ret = copy_Name(issuername, &tbsc->issuer); else ret = hx509_name_to_Name(tbs->subject, &tbsc->issuer); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to copy issuer name"); goto out; } /* validity Validity, */ tbsc->validity.notBefore.element = choice_Time_generalTime; tbsc->validity.notBefore.u.generalTime = notBefore; tbsc->validity.notAfter.element = choice_Time_generalTime; tbsc->validity.notAfter.u.generalTime = notAfter; /* subject Name, */ if (tbs->flags.proxy) { ret = build_proxy_prefix(context, &tbsc->issuer, &tbsc->subject); if (ret) goto out; } else { ret = hx509_name_to_Name(tbs->subject, &tbsc->subject); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to copy subject name"); goto out; } } /* subjectPublicKeyInfo SubjectPublicKeyInfo, */ ret = copy_SubjectPublicKeyInfo(&tbs->spki, &tbsc->subjectPublicKeyInfo); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to copy spki"); goto out; } /* issuerUniqueID [1] IMPLICIT BIT STRING OPTIONAL */ /* subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL */ /* extensions [3] EXPLICIT Extensions OPTIONAL */ tbsc->extensions = calloc(1, sizeof(*tbsc->extensions)); if (tbsc->extensions == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } /* Add the text BMP string Domaincontroller to the cert */ if (tbs->flags.domaincontroller) { data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d" "\x00\x61\x00\x69\x00\x6e\x00\x43" "\x00\x6f\x00\x6e\x00\x74\x00\x72" "\x00\x6f\x00\x6c\x00\x6c\x00\x65" "\x00\x72"); data.length = 34; ret = add_extension(context, tbsc, 0, oid_id_ms_cert_enroll_domaincontroller(), &data); if (ret) goto out; } /* add KeyUsage */ { KeyUsage ku; ku = int2KeyUsage(key_usage); ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length, &ku, &size, ret); if (ret) { hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } if (size != data.length) _hx509_abort("internal ASN.1 encoder error"); ret = add_extension(context, tbsc, 1, oid_id_x509_ce_keyUsage(), &data); free(data.data); if (ret) goto out; } /* add ExtendedKeyUsage */ if (tbs->eku.len > 0) { ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length, &tbs->eku, &size, ret); if (ret) { hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } if (size != data.length) _hx509_abort("internal ASN.1 encoder error"); ret = add_extension(context, tbsc, 0, oid_id_x509_ce_extKeyUsage(), &data); free(data.data); if (ret) goto out; } /* add Subject Alternative Name */ if (tbs->san.len > 0) { ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length, &tbs->san, &size, ret); if (ret) { hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } if (size != data.length) _hx509_abort("internal ASN.1 encoder error"); ret = add_extension(context, tbsc, 0, oid_id_x509_ce_subjectAltName(), &data); free(data.data); if (ret) goto out; } /* Add Authority Key Identifier */ if (ai) { ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length, ai, &size, ret); if (ret) { hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } if (size != data.length) _hx509_abort("internal ASN.1 encoder error"); ret = add_extension(context, tbsc, 0, oid_id_x509_ce_authorityKeyIdentifier(), &data); free(data.data); if (ret) goto out; } /* Add Subject Key Identifier */ { SubjectKeyIdentifier si; unsigned char hash[SHA_DIGEST_LENGTH]; { SHA_CTX m; SHA1_Init(&m); SHA1_Update(&m, tbs->spki.subjectPublicKey.data, tbs->spki.subjectPublicKey.length / 8); SHA1_Final (hash, &m); } si.data = hash; si.length = sizeof(hash); ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length, &si, &size, ret); if (ret) { hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } if (size != data.length) _hx509_abort("internal ASN.1 encoder error"); ret = add_extension(context, tbsc, 0, oid_id_x509_ce_subjectKeyIdentifier(), &data); free(data.data); if (ret) goto out; } /* Add BasicConstraints */ { BasicConstraints bc; int aCA = 1; uint32_t path; memset(&bc, 0, sizeof(bc)); if (tbs->flags.ca) { bc.cA = &aCA; if (tbs->pathLenConstraint >= 0) { path = tbs->pathLenConstraint; bc.pathLenConstraint = &path; } } ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length, &bc, &size, ret); if (ret) { hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } if (size != data.length) _hx509_abort("internal ASN.1 encoder error"); /* Critical if this is a CA */ ret = add_extension(context, tbsc, tbs->flags.ca, oid_id_x509_ce_basicConstraints(), &data); free(data.data); if (ret) goto out; } /* add Proxy */ if (tbs->flags.proxy) { ProxyCertInfo info; memset(&info, 0, sizeof(info)); if (tbs->pathLenConstraint >= 0) { info.pCPathLenConstraint = malloc(sizeof(*info.pCPathLenConstraint)); if (info.pCPathLenConstraint == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } *info.pCPathLenConstraint = tbs->pathLenConstraint; } ret = der_copy_oid(oid_id_pkix_ppl_inheritAll(), &info.proxyPolicy.policyLanguage); if (ret) { free_ProxyCertInfo(&info); hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length, &info, &size, ret); free_ProxyCertInfo(&info); if (ret) { hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } if (size != data.length) _hx509_abort("internal ASN.1 encoder error"); ret = add_extension(context, tbsc, 0, oid_id_pkix_pe_proxyCertInfo(), &data); free(data.data); if (ret) goto out; } if (tbs->crldp.len) { ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length, &tbs->crldp, &size, ret); if (ret) { hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } if (size != data.length) _hx509_abort("internal ASN.1 encoder error"); ret = add_extension(context, tbsc, FALSE, oid_id_x509_ce_cRLDistributionPoints(), &data); free(data.data); if (ret) goto out; } ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret); if (ret) { hx509_set_error_string(context, 0, ret, "malloc out of memory"); goto out; } if (data.length != size) _hx509_abort("internal ASN.1 encoder error"); ret = _hx509_create_signature_bitstring(context, signer, sigalg, &data, &c.signatureAlgorithm, &c.signatureValue); free(data.data); if (ret) goto out; ret = hx509_cert_init(context, &c, certificate); if (ret) goto out; free_Certificate(&c); return 0;out: free_Certificate(&c); return ret;}static intget_AuthorityKeyIdentifier(hx509_context context, const Certificate *certificate, AuthorityKeyIdentifier *ai){ SubjectKeyIdentifier si; int ret; ret = _hx509_find_extension_subject_key_id(certificate, &si); if (ret == 0) { ai->keyIdentifier = calloc(1, sizeof(*ai->keyIdentifier)); if (ai->keyIdentifier == NULL) { free_SubjectKeyIdentifier(&si); ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } ret = der_copy_octet_string(&si, ai->keyIdentifier); free_SubjectKeyIdentifier(&si); if (ret) { hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } } else { GeneralNames gns; GeneralName gn; Name name; memset(&gn, 0, sizeof(gn)); memset(&gns, 0, sizeof(gns)); memset(&name, 0, sizeof(name)); ai->authorityCertIssuer = calloc(1, sizeof(*ai->authorityCertIssuer)); if (ai->authorityCertIssuer == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } ai->authorityCertSerialNumber = calloc(1, sizeof(*ai->authorityCertSerialNumber)); if (ai->authorityCertSerialNumber == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } /* * XXX unbreak when asn1 compiler handle IMPLICIT * * This is so horrible. */ ret = copy_Name(&certificate->tbsCertificate.subject, &name); if (ai->authorityCertSerialNumber == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } memset(&gn, 0, sizeof(gn)); gn.element = choice_GeneralName_directoryName; gn.u.directoryName.element = choice_GeneralName_directoryName_rdnSequence; gn.u.directoryName.u.rdnSequence = name.u.rdnSequence; ret = add_GeneralNames(&gns, &gn); if (ret) { hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } ai->authorityCertIssuer->val = gns.val; ai->authorityCertIssuer->len = gns.len; ret = der_copy_heim_integer(&certificate->tbsCertificate.serialNumber, ai->authorityCertSerialNumber); if (ai->authorityCertSerialNumber == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; } }out: if (ret) free_AuthorityKeyIdentifier(ai); return ret;}/** * Sign a to-be-signed certificate object with a issuer certificate. * * The caller needs to at least have called the following functions on the * to-be-signed certificate object: * - hx509_ca_tbs_init() * - hx509_ca_tbs_set_subject() * - hx509_ca_tbs_set_spki() * * When done the to-be-signed certificate object should be freed with * hx509_ca_tbs_free(). * * When creating self-signed certificate use hx509_ca_sign_self() instead. * * @param context A hx509 context. * @param tbs object to be signed. * @param signer the CA certificate object to sign with (need private key). * @param certificate return cerificate, free with hx509_cert_free(). * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_ca */inthx509_ca_sign(hx509_context context, hx509_ca_tbs tbs, hx509_cert signer, hx509_cert *certificate){ const Certificate *signer_cert; AuthorityKeyIdentifier ai; int ret; memset(&ai, 0, sizeof(ai)); signer_cert = _hx509_get_cert(signer); ret = get_AuthorityKeyIdentifier(context, signer_cert, &ai); if (ret) goto out; ret = ca_sign(context, tbs, _hx509_cert_private_key(signer), &ai, &signer_cert->tbsCertificate.subject, certificate);out: free_AuthorityKeyIdentifier(&ai); return ret;}/** * Work just like hx509_ca_sign() but signs it-self. * * @param context A hx509 context. * @param tbs object to be signed. * @param signer private key to sign with. * @param certificate return cerificate, free with hx509_cert_free(). * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_ca */inthx509_ca_sign_self(hx509_context context, hx509_ca_tbs tbs, hx509_private_key signer, hx509_cert *certificate){ return ca_sign(context, tbs, signer, NULL, NULL, certificate);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -