cgmnlm

colorful gemini line mode browser
git clone https://git.clttr.info/cgmnlm.git
Log (Feed) | Files | Refs (Tags) | README | LICENSE

certs.c (3832B)


      1 #include <assert.h>
      2 #include <bearssl.h>
      3 #include <errno.h>
      4 #include <gmni/certs.h>
      5 #include <gmni/gmni.h>
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 
      9 static void
     10 crt_append(void *ctx, const void *src, size_t len)
     11 {
     12 	br_x509_certificate *crt = (br_x509_certificate *)ctx;
     13 	crt->data = realloc(crt->data, crt->data_len + len);
     14 	assert(crt->data);
     15 	memcpy(&crt->data[crt->data_len], src, len);
     16 	crt->data_len += len;
     17 }
     18 
     19 static void
     20 key_append(void *ctx, const void *src, size_t len)
     21 {
     22 	br_skey_decoder_context *skctx = (br_skey_decoder_context *)ctx;
     23 	br_skey_decoder_push(skctx, src, len);
     24 }
     25 
     26 int
     27 gmni_ccert_load(struct gmni_client_certificate *cert, FILE *certin, FILE *skin)
     28 {
     29 	// TODO: Better error propagation to caller
     30 	static unsigned char buf[BUFSIZ];
     31 
     32 	br_pem_decoder_context pemdec;
     33 	br_pem_decoder_init(&pemdec);
     34 
     35 	cert->chain = NULL;
     36 	cert->nchain = 0;
     37 
     38 	static const char *certname = "CERTIFICATE";
     39 	while (!feof(certin)) {
     40 		size_t n = fread(&buf, 1, sizeof(buf), certin);
     41 		if (ferror(certin)) {
     42 			goto error;
     43 		}
     44 		size_t q = 0;
     45 		while (q < n) {
     46 			q += br_pem_decoder_push(&pemdec, &buf[q], n - q);
     47 			switch (br_pem_decoder_event(&pemdec)) {
     48 			case BR_PEM_BEGIN_OBJ:
     49 				if (strcmp(br_pem_decoder_name(&pemdec), certname) != 0) {
     50 					break;
     51 				}
     52 				cert->chain = realloc(cert->chain,
     53 					sizeof(br_x509_certificate) * (cert->nchain + 1));
     54 				memset(&cert->chain[cert->nchain], 0, sizeof(*cert->chain));
     55 				br_pem_decoder_setdest(&pemdec, &crt_append,
     56 						&cert->chain[cert->nchain]);
     57 				++cert->nchain;
     58 				break;
     59 			case BR_PEM_END_OBJ:
     60 				break;
     61 			case BR_PEM_ERROR:
     62 				fprintf(stderr, "Error decoding PEM certificate\n");
     63 				errno = EINVAL;
     64 				goto error;
     65 			}
     66 		}
     67 	}
     68 
     69 	if (cert->nchain == 0) {
     70 		fprintf(stderr, "No certificates found in provided client certificate file\n");
     71 		errno = EINVAL;
     72 		goto error;
     73 	}
     74 
     75 	br_skey_decoder_context skdec = {0};
     76 	br_skey_decoder_init(&skdec);
     77 	br_pem_decoder_init(&pemdec);
     78 
     79 	// TODO: Better validation of PEM file
     80 	while (!feof(skin)) {
     81 		size_t n = fread(&buf, 1, sizeof(buf), skin);
     82 		if (ferror(skin)) {
     83 			goto error;
     84 		}
     85 		size_t q = 0;
     86 		while (q < n) {
     87 			q += br_pem_decoder_push(&pemdec, &buf[q], n - q);
     88 			switch (br_pem_decoder_event(&pemdec)) {
     89 			case BR_PEM_BEGIN_OBJ:
     90 				br_pem_decoder_setdest(&pemdec, &key_append, &skdec);
     91 				break;
     92 			case BR_PEM_END_OBJ:
     93 				// no-op
     94 				break;
     95 			case BR_PEM_ERROR:
     96 				fprintf(stderr, "Error decoding PEM private key\n");
     97 				errno = EINVAL;
     98 				goto error;
     99 			}
    100 		}
    101 	}
    102 
    103 	int err = br_skey_decoder_last_error(&skdec);
    104 	if (err != 0) {
    105 		fprintf(stderr, "Error loading private key: %d\n", err);
    106 		errno = EINVAL;
    107 		goto error;
    108 	}
    109 	switch (br_skey_decoder_key_type(&skdec)) {
    110 		struct gmni_private_key *k;
    111 		const br_ec_private_key *ec;
    112 		const br_rsa_private_key *rsa;
    113 	case BR_KEYTYPE_RSA:
    114 		rsa = br_skey_decoder_get_rsa(&skdec);
    115 		cert->key = k = malloc(sizeof(*k)
    116 				+ rsa->plen + rsa->qlen
    117 				+ rsa->dplen + rsa->dqlen
    118 				+ rsa->iqlen);
    119 		assert(k);
    120 		k->type = BR_KEYTYPE_RSA;
    121 		k->rsa = *rsa;
    122 		k->rsa.p = k->data;
    123 		k->rsa.q = k->rsa.p + k->rsa.plen;
    124 		k->rsa.dp = k->rsa.q + k->rsa.qlen;
    125 		k->rsa.dq = k->rsa.dp + k->rsa.dplen;
    126 		k->rsa.iq = k->rsa.dq + k->rsa.dqlen;
    127 		memcpy(k->rsa.p, rsa->p, rsa->plen);
    128 		memcpy(k->rsa.q, rsa->q, rsa->qlen);
    129 		memcpy(k->rsa.dp, rsa->dp, rsa->dplen);
    130 		memcpy(k->rsa.dq, rsa->dq, rsa->dqlen);
    131 		memcpy(k->rsa.iq, rsa->iq, rsa->iqlen);
    132 		break;
    133 	case BR_KEYTYPE_EC:
    134 		ec = br_skey_decoder_get_ec(&skdec);
    135 		cert->key = k = malloc(sizeof(*k) + ec->xlen);
    136 		assert(k);
    137 		k->type = BR_KEYTYPE_EC;
    138 		k->ec.curve = ec->curve;
    139 		k->ec.x = k->data;
    140 		k->ec.xlen = ec->xlen;
    141 		memcpy(k->ec.x, ec->x, ec->xlen);
    142 		break;
    143 	default:
    144 		assert(0);
    145 	}
    146 
    147 	fclose(certin);
    148 	fclose(skin);
    149 	return 0;
    150 
    151 error:
    152 	fclose(certin);
    153 	fclose(skin);
    154 	free(cert->chain);
    155 	return 1;
    156 }