Crypt-Bear
view release on metacpan or search on metacpan
src/x509/x509_minimal.c view on Meta::CPAN
}
static int32_t
t0_parse7E_signed(const unsigned char **p)
{
int neg;
uint32_t x;
neg = ((**p) >> 6) & 1;
x = (uint32_t)-neg;
for (;;) {
unsigned y;
y = *(*p) ++;
x = (x << 7) | (uint32_t)(y & 0x7F);
if (y < 0x80) {
if (neg) {
return -(int32_t)~x - 1;
} else {
return (int32_t)x;
}
}
}
}
#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80)
#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F)
#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8)
#define T0_INT1(x) T0_FBYTE(x, 0)
#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0)
#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
/* static const unsigned char t0_datablock[]; */
void br_x509_minimal_init_main(void *t0ctx);
void br_x509_minimal_run(void *t0ctx);
#include "inner.h"
#include "inner.h"
/*
* Implementation Notes
* --------------------
*
* The C code pushes the data by chunks; all decoding is done in the
* T0 code. The cert_length value is set to the certificate length when
* a new certificate is started; the T0 code picks it up as outer limit,
* and decoding functions use it to ensure that no attempt is made at
* reading past it. The T0 code also checks that once the certificate is
* decoded, there are no trailing bytes.
*
* The T0 code sets cert_length to 0 when the certificate is fully
* decoded.
*
* The C code must still perform two checks:
*
* -- If the certificate length is 0, then the T0 code will not be
* invoked at all. This invalid condition must thus be reported by the
* C code.
*
* -- When reaching the end of certificate, the C code must verify that
* the certificate length has been set to 0, thereby signaling that
* the T0 code properly decoded a certificate.
*
* Processing of a chain works in the following way:
*
* -- The error flag is set to a non-zero value when validation is
* finished. The value is either BR_ERR_X509_OK (validation is
* successful) or another non-zero error code. When a non-zero error
* code is obtained, the remaining bytes in the current certificate and
* the subsequent certificates (if any) are completely ignored.
*
* -- Each certificate is decoded in due course, with the following
* "interesting points":
*
* -- Start of the TBS: the multihash engine is reset and activated.
*
* -- Start of the issuer DN: the secondary hash engine is started,
* to process the encoded issuer DN.
*
* -- End of the issuer DN: the secondary hash engine is stopped. The
* resulting hash value is computed and then copied into the
* next_dn_hash[] buffer.
*
* -- Start of the subject DN: the secondary hash engine is started,
* to process the encoded subject DN.
*
* -- For the EE certificate only: the Common Name, if any, is matched
* against the expected server name.
*
* -- End of the subject DN: the secondary hash engine is stopped. The
* resulting hash value is computed into the pad. It is then processed:
*
* -- If this is the EE certificate, then the hash is ignored
* (except for direct trust processing, see later; the hash is
* simply left in current_dn_hash[]).
*
* -- Otherwise, the hashed subject DN is compared with the saved
* hash value (in saved_dn_hash[]). They must match.
*
* Either way, the next_dn_hash[] value is then copied into the
* saved_dn_hash[] value. Thus, at that point, saved_dn_hash[]
* contains the hash of the issuer DN for the current certificate,
* and current_dn_hash[] contains the hash of the subject DN for the
* current certificate.
*
* -- Public key: it is decoded into the cert_pkey[] buffer. Unknown
* key types are reported at that point.
*
* -- If this is the EE certificate, then the key type is compared
* with the expected key type (initialization parameter). The public
* key data is copied to ee_pkey_data[]. The key and hashed subject
* DN are also compared with the "direct trust" keys; if the key
* and DN are matched, then validation ends with a success.
*
* -- Otherwise, the saved signature (cert_sig[]) is verified
* against the saved TBS hash (tbs_hash[]) and that freshly
* decoded public key. Failure here ends validation with an error.
*
* -- Extensions: extension values are processed in due order.
*
* -- Basic Constraints: for all certificates except EE, must be
* present, indicate a CA, and have a path length compatible with
* the chain length so far.
*
* -- Key Usage: for the EE, if present, must allow signatures
* or encryption/key exchange, as required for the cipher suite.
* For non-EE, if present, must have the "certificate sign" bit.
*
* -- Subject Alt Name: for the EE, dNSName names are matched
* against the server name. Ignored for non-EE.
*
* -- Authority Key Identifier, Subject Key Identifier, Issuer
* Alt Name, Subject Directory Attributes, CRL Distribution Points
* Freshest CRL, Authority Info Access and Subject Info Access
* extensions are always ignored: they either contain only
* informative data, or they relate to revocation processing, which
* we explicitly do not support.
*
* -- All other extensions are ignored if non-critical. If a
* critical extension other than the ones above is encountered,
* then a failure is reported.
*
* -- End of the TBS: the multihash engine is stopped.
*
* -- Signature algorithm: the signature algorithm on the
* certificate is decoded. A failure is reported if that algorithm
* is unknown. The hashed TBS corresponding to the signature hash
* function is computed and stored in tbs_hash[] (if not supported,
* then a failure is reported). The hash OID and length are stored
* in cert_sig_hash_oid and cert_sig_hash_len.
*
* -- Signature value: the signature value is copied into the
* cert_sig[] array.
*
* -- Certificate end: the hashed issuer DN (saved_dn_hash[]) is
* looked up in the trust store (CA trust anchors only); for all
* that match, the signature (cert_sig[]) is verified against the
* anchor public key (hashed TBS is in tbs_hash[]). If one of these
* signatures is valid, then validation ends with a success.
*
* -- If the chain end is reached without obtaining a validation success,
* then validation is reported as failed.
*/
#if BR_USE_UNIX_TIME
#include <time.h>
#endif
#if BR_USE_WIN32_TIME
#include <windows.h>
#endif
/*
* The T0 compiler will produce these prototypes declarations in the
* header.
*
void br_x509_minimal_init_main(void *ctx);
void br_x509_minimal_run(void *ctx);
*/
/* see bearssl_x509.h */
void
br_x509_minimal_init(br_x509_minimal_context *ctx,
const br_hash_class *dn_hash_impl,
const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num)
{
memset(ctx, 0, sizeof *ctx);
ctx->vtable = &br_x509_minimal_vtable;
ctx->dn_hash_impl = dn_hash_impl;
ctx->trust_anchors = trust_anchors;
ctx->trust_anchors_num = trust_anchors_num;
}
static void
xm_start_chain(const br_x509_class **ctx, const char *server_name)
{
br_x509_minimal_context *cc;
size_t u;
cc = (br_x509_minimal_context *)(void *)ctx;
for (u = 0; u < cc->num_name_elts; u ++) {
cc->name_elts[u].status = 0;
cc->name_elts[u].buf[0] = 0;
}
memset(&cc->pkey, 0, sizeof cc->pkey);
cc->num_certs = 0;
( run in 2.247 seconds using v1.01-cache-2.11-cpan-d8267643d1d )