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 }