hx509: always verify CSR signature
This commit is contained in:
142
lib/hx509/req.c
142
lib/hx509/req.c
@@ -238,70 +238,108 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
HX509_LIB_FUNCTION int HX509_LIB_CALL
|
HX509_LIB_FUNCTION int HX509_LIB_CALL
|
||||||
_hx509_request_parse(hx509_context context,
|
_hx509_request_parse_der(hx509_context context,
|
||||||
const char *path,
|
heim_octet_string *der,
|
||||||
hx509_request *req)
|
hx509_request *req)
|
||||||
{
|
{
|
||||||
|
CertificationRequestInfo *rinfo = NULL;
|
||||||
CertificationRequest r;
|
CertificationRequest r;
|
||||||
CertificationRequestInfo *rinfo;
|
Certificate c;
|
||||||
hx509_name subject;
|
hx509_name subject = NULL;
|
||||||
size_t len, size;
|
hx509_cert signer = NULL;
|
||||||
void *p;
|
size_t size;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (strncmp(path, "PKCS10:", 7) != 0) {
|
ret = decode_CertificationRequest(der->data, der->length, &r, &size);
|
||||||
|
if (ret) {
|
||||||
|
hx509_set_error_string(context, 0, ret, "Failed to decode CSR");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
rinfo = &r.certificationRequestInfo;
|
||||||
|
if (ret == 0) {
|
||||||
|
/*
|
||||||
|
* Sadly we need an hx509_cert here because _hx509_verify_signature_*()
|
||||||
|
* functions want one as a signer even though all the verification
|
||||||
|
* functions that use the signer argument always only use the spki of
|
||||||
|
* the signer certificate.
|
||||||
|
*
|
||||||
|
* XXX Change struct signature_alg's verify_signature's prototype to
|
||||||
|
* use an spki instead of an hx509_cert as the signer! The we
|
||||||
|
* won't have to do this.
|
||||||
|
*/
|
||||||
|
memset(&c, 0, sizeof(c));
|
||||||
|
c.tbsCertificate.subjectPublicKeyInfo = rinfo->subjectPKInfo;
|
||||||
|
if ((signer = hx509_cert_init(context, &c, NULL)) == NULL)
|
||||||
|
ret = ENOMEM;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify the signature */
|
||||||
|
if (ret == 0) {
|
||||||
|
heim_octet_string *d = &r.certificationRequestInfo._save;
|
||||||
|
|
||||||
|
ret = _hx509_verify_signature_bitstring(context, signer,
|
||||||
|
&r.signatureAlgorithm, d,
|
||||||
|
&r.signature);
|
||||||
|
if (ret)
|
||||||
|
hx509_set_error_string(context, 0, ret,
|
||||||
|
"CSR signature verification failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build and populate the hx509_request */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = hx509_request_init(context, req);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = hx509_request_set_SubjectPublicKeyInfo(context, *req,
|
||||||
|
&rinfo->subjectPKInfo);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = _hx509_name_from_Name(&rinfo->subject, &subject);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = hx509_request_set_name(context, *req, subject);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX Extract EKUs and SANs from the CSR's attributes. That means looking
|
||||||
|
* for an attr of OID asn1_oid_id_x509_ce_subjectAltName
|
||||||
|
* (id-ce-subjectAltName) and decoding their values. See RFC5912.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (subject)
|
||||||
|
hx509_name_free(&subject);
|
||||||
|
if (signer)
|
||||||
|
hx509_cert_free(signer);
|
||||||
|
if (ret)
|
||||||
|
hx509_request_free(req);
|
||||||
|
free_CertificationRequest(&r);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
HX509_LIB_FUNCTION int HX509_LIB_CALL
|
||||||
|
_hx509_request_parse(hx509_context context,
|
||||||
|
const char *csr,
|
||||||
|
hx509_request *req)
|
||||||
|
{
|
||||||
|
heim_octet_string d;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* XXX Add support for PEM */
|
||||||
|
if (strncmp(csr, "PKCS10:", 7) != 0) {
|
||||||
hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
|
hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
|
||||||
"unsupport type in %s", path);
|
"unsupport type in %s", csr);
|
||||||
return HX509_UNSUPPORTED_OPERATION;
|
return HX509_UNSUPPORTED_OPERATION;
|
||||||
}
|
}
|
||||||
path += 7;
|
|
||||||
|
|
||||||
/* XXX PEM request */
|
ret = rk_undumpdata(csr + 7, &d.data, &d.length);
|
||||||
|
|
||||||
ret = rk_undumpdata(path, &p, &len);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
hx509_set_error_string(context, 0, ret, "Failed to map file %s", path);
|
hx509_set_error_string(context, 0, ret, "Could not read %s", csr);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = decode_CertificationRequest(p, len, &r, &size);
|
ret = _hx509_request_parse_der(context, &d, req);
|
||||||
rk_xfree(p);
|
free(d.data);
|
||||||
if (ret) {
|
if (ret)
|
||||||
hx509_set_error_string(context, 0, ret, "Failed to decode %s", path);
|
hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
|
||||||
return ret;
|
" (while parsing CSR from %s)", csr);
|
||||||
}
|
return ret;
|
||||||
|
|
||||||
ret = hx509_request_init(context, req);
|
|
||||||
if (ret) {
|
|
||||||
free_CertificationRequest(&r);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
rinfo = &r.certificationRequestInfo;
|
|
||||||
|
|
||||||
ret = hx509_request_set_SubjectPublicKeyInfo(context, *req,
|
|
||||||
&rinfo->subjectPKInfo);
|
|
||||||
if (ret) {
|
|
||||||
free_CertificationRequest(&r);
|
|
||||||
hx509_request_free(req);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = _hx509_name_from_Name(&rinfo->subject, &subject);
|
|
||||||
if (ret) {
|
|
||||||
free_CertificationRequest(&r);
|
|
||||||
hx509_request_free(req);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret = hx509_request_set_name(context, *req, subject);
|
|
||||||
hx509_name_free(&subject);
|
|
||||||
free_CertificationRequest(&r);
|
|
||||||
if (ret) {
|
|
||||||
hx509_request_free(req);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user