/* generate a transaction id as the MD5 hash of an public key * the transaction id is also used as a unique serial number */ void scep_generate_transaction_id(const RSA_public_key_t *rsak , chunk_t *transID, chunk_t *serialNumber) { char buf[MD5_DIGEST_SIZE]; chunk_t digest = { buf, sizeof(buf) }; chunk_t public_key = pkcs1_build_publicKeyInfo(rsak); bool msb_set; u_char *pos; compute_digest(public_key, OID_MD5, &digest); pfree(public_key.ptr); /* is the most significant bit of the digest set? */ msb_set = (*digest.ptr & 0x80) == 0x80; /* allocate space for the serialNumber */ serialNumber->len = msb_set + digest.len; serialNumber->ptr = alloc_bytes(serialNumber->len, "serialNumber"); /* the serial number as the two's complement of the digest */ pos = serialNumber->ptr; if (msb_set) { *pos++ = 0x00; } memcpy(pos, digest.ptr, digest.len); /* the transaction id is the serial number in hex format */ transID->len = 2*digest.len; transID->ptr = alloc_bytes(transID->len + 1, "transID"); datatot(digest.ptr, digest.len, 16, transID->ptr, transID->len + 1); }
/* converts a binary request to base64 with 64 characters per line * newline and '+' characters are escaped by %0A and %2B, respectively */ static char* escape_http_request(chunk_t req) { char *escaped_req = NULL; char *p1, *p2; int lines = 0; int plus = 0; int n = 0; /* compute and allocate the size of the base64-encoded request */ int len = 1 + 4*((req.len + 2)/3); char *encoded_req = alloc_bytes(len, "encoded request"); /* do the base64 conversion */ len = datatot(req.ptr, req.len, 64, encoded_req, len); /* compute newline characters to be inserted every 64 characters */ lines = (len - 2) / 64; /* count number of + characters to be escaped */ p1 = encoded_req; while (*p1 != '\0') { if (*p1++ == '+') plus++; } escaped_req = alloc_bytes(len + 3*(lines + plus), "escaped request"); /* escape special characters in the request */ p1 = encoded_req; p2 = escaped_req; while (*p1 != '\0') { if (n == 64) { memcpy(p2, "%0A", 3); p2 += 3; n = 0; } if (*p1 == '+') { memcpy(p2, "%2B", 3); p2 += 3; } else { *p2++ = *p1; } p1++; n++; } *p2 = '\0'; pfreeany(encoded_req); return escaped_req; }
static void read_foodgroup(struct fg_groups *g) { const char *fgn = g->connection->name; const ip_subnet *lsn = &g->connection->spd.this.client; const struct lsw_conf_options *oco = lsw_init_options(); size_t plen = strlen(oco->policies_dir) + 2 + strlen(fgn) + 1; struct file_lex_position flp_space; if (plen > fg_path_space) { pfreeany(fg_path); fg_path_space = plen + 10; fg_path = alloc_bytes(fg_path_space, "policy group path"); } snprintf(fg_path, fg_path_space, "%s/%s", oco->policies_dir, fgn); if (!lexopen(&flp_space, fg_path, TRUE)) { DBG(DBG_CONTROL, char cwd[PATH_MAX]; DBG_log("no group file \"%s\" (pwd:%s)" , fg_path , getcwd(cwd, sizeof(cwd)))); }
/* Expand storage for transforms by number delta_trans */ static int db_trans_expand(struct db_context *ctx, int delta_trans) { int ret = -1; struct db_trans *new_trans, *old_trans; int max_trans = ctx->max_trans + delta_trans; int offset; old_trans = ctx->trans0; new_trans = alloc_bytes ( sizeof (struct db_trans) * max_trans, "db_context->trans (expand)"); if (!new_trans) goto out; memcpy(new_trans, old_trans, ctx->max_trans * sizeof(struct db_trans)); /* update trans0 (obviously) */ ctx->trans0 = ctx->prop.trans = new_trans; /* update trans_cur (by offset) */ offset = (char *)(new_trans) - (char *)(old_trans); (char *)(ctx->trans_cur) += offset; /* update elem count */ ctx->max_trans = max_trans; pfree(old_trans); ret = 0; out: return ret; }
static bool pluto_init_nss(char *nssdb) { SECStatus rv; /* little lie, lsw_nss_setup doesn't have logging */ loglog(RC_LOG_SERIOUS, "NSS DB directory: sql:%s", nssdb); lsw_nss_buf_t err; if (!lsw_nss_setup(nssdb, LSW_NSS_READONLY, lsw_nss_get_password, err)) { loglog(RC_LOG_SERIOUS, "%s", err); return FALSE; } libreswan_log("NSS initialized"); /* * This exists purely to make the BSI happy. * We do not inflict this on other users */ if (pluto_nss_seedbits != 0) { int seedbytes = BYTES_FOR_BITS(pluto_nss_seedbits); unsigned char *buf = alloc_bytes(seedbytes,"TLA seedmix"); get_bsi_random(seedbytes, buf); /* much TLA, very blocking */ rv = PK11_RandomUpdate(buf, seedbytes); libreswan_log("seeded %d bytes into the NSS PRNG", seedbytes); passert(rv == SECSuccess); messupn(buf, seedbytes); pfree(buf); } return TRUE; }
static bool pluto_init_nss(char *nssdb) { SECStatus rv; char dbuf[1024]; snprintf(dbuf, sizeof(dbuf), "sql:%s", nssdb); loglog(RC_LOG_SERIOUS, "NSS DB directory: %s", dbuf); rv = NSS_Initialize(dbuf, "", "", SECMOD_DB, NSS_INIT_READONLY); if (rv != SECSuccess) { loglog(RC_LOG_SERIOUS, "NSS readonly initialization (\"%s\") failed (err %d)\n", dbuf, PR_GetError()); return FALSE; } libreswan_log("NSS initialized"); PK11_SetPasswordFunc(getNSSPassword); /* * This exists purely to make the BSI happy. * We do not inflict this on other users */ if (pluto_nss_seedbits != 0) { int seedbytes = BYTES_FOR_BITS(pluto_nss_seedbits); unsigned char *buf = alloc_bytes(seedbytes,"TLA seedmix"); get_bsi_random(seedbytes, buf); /* much TLA, very blocking */ rv = PK11_RandomUpdate(buf, seedbytes); libreswan_log("seeded %d bytes into the NSS PRNG", seedbytes); passert(rv == SECSuccess); messupn(buf, seedbytes); pfree(buf); } return TRUE; }
/* get a response to a specific message */ static bool pfkey_get_response(pfkey_buf *buf, pfkey_seq_t seq) { while (pfkey_get(buf)) { if (buf->msg.sadb_msg_pid == (unsigned)pid && buf->msg.sadb_msg_seq == seq) { return TRUE; } else { /* Not for us: queue it. */ size_t bl = buf->msg.sadb_msg_len * IPSEC_PFKEYv2_ALIGN; pfkey_item *it = alloc_bytes(offsetof(pfkey_item, buf) + bl, "pfkey_item"); memcpy(&it->buf, buf, bl); it->next = NULL; if (pfkey_iq_head == NULL) { pfkey_iq_head = it; } else { pfkey_iq_tail->next = it; } pfkey_iq_tail = it; } } return FALSE; }
/* Convert MP_INT to network form (binary octets, big-endian). * We do the malloc; caller must eventually do free. */ chunk_t mpz_to_n(const MP_INT *mp, size_t bytes) { chunk_t r; MP_INT temp1, temp2; int i; r.len = bytes; r.ptr = alloc_bytes(r.len, "host representation of large integer"); mpz_init(&temp1); mpz_init(&temp2); mpz_set(&temp1, mp); for (i = r.len-1; i >= 0; i--) { r.ptr[i] = mpz_mdivmod_ui(&temp2, NULL, &temp1, 1 << BITS_PER_BYTE); mpz_set(&temp1, &temp2); } passert(mpz_sgn(&temp1) == 0); /* we must have done all the bits */ mpz_clear(&temp1); mpz_clear(&temp2); return r; }
/* load a coded key or certificate file with autodetection * of binary DER or base64 PEM ASN.1 formats and armored PGP format */ bool load_coded_file(const char *filename, prompt_pass_t *pass, int verbose, const char *type, chunk_t *blob, bool *pgp) { err_t ugh = NULL; FILE *fd; fd = fopen(filename, "r"); if (fd) { int bytes; fseek(fd, 0, SEEK_END ); blob->len = ftell(fd); rewind(fd); blob->ptr = alloc_bytes(blob->len, type); bytes = fread(blob->ptr, 1, blob->len, fd); fclose(fd); if(verbose) { openswan_log(" loaded %s file '%s' (%d bytes)", type, filename, bytes); } *pgp = FALSE; /* try DER format */ if (is_asn1(*blob)) { DBG(DBG_PARSING, DBG_log(" file coded in DER format"); ) return TRUE; }
/* format error, and append to string of errors */ static bool error_append(char **perr, const char *fmt, ...) { static char tmp_err[512]; va_list args; char *nerr; int len; va_start(args, fmt); vsnprintf(tmp_err, sizeof(tmp_err) - 1, fmt, args); va_end(args); len = 1 + strlen(tmp_err) + (*perr != NULL ? strlen(*perr) : 0); nerr = alloc_bytes(len, "error_append len"); nerr[0] = '\0'; if (*perr != NULL) { strcpy(nerr, *perr); /* safe: see allocation above */ pfree(*perr); } strcat(nerr, tmp_err); /* safe: see allocation above */ *perr = nerr; return TRUE; }
void calculate_rsa_ckaid(osw_public_key *pub) { if(pub->alg == PUBKEY_ALG_RSA) { struct RSA_public_key *rsa = &pub->u.rsa; if(rsa->key_rfc3110.len == 0) { /* key has no 3110 representation, need to cons up one */ unsigned int e_size = mpz_sizeinbase(&rsa->e, 256); unsigned int key3110len = rsa->k + 1 + e_size; rsa->key_rfc3110.ptr = alloc_bytes(key3110len, "rfc3110 format of public key [created]"); rsa->key_rfc3110.len = key3110len; unsigned char *here = rsa->key_rfc3110.ptr; here[0] = e_size; here++; mpz_export(here, NULL, 1, 1, 1, 0, &rsa->e); here += e_size; mpz_export(here, NULL, 1, 1, 1, 0, &rsa->n); } /* maybe #ifdef SHA2 ? */ /* calculate the hash of the public key, using SHA-2 */ sha256_hash_buffer(rsa->key_rfc3110.ptr, rsa->key_rfc3110.len, pub->key_ckaid, sizeof(pub->key_ckaid)); datatot(pub->key_ckaid, sizeof(pub->key_ckaid), 'G', pub->key_ckaid_print_buf, sizeof(pub->key_ckaid_print_buf)); } }
MPI mpi_copy( MPI a ) { MPI n = alloc_bytes(sizeof *n, "mpi_copy"); mpz_init_set(n, a); return n; }
MPI mpi_alloc_set_ui( unsigned long u) { MPI n = alloc_bytes(sizeof *n, "mpi_copy"); mpz_init_set_ui(n, u); return n; }
MPI mpi_alloc( unsigned nlimbs UNUSED ) { MPI n = alloc_bytes(sizeof *n, "mpi_alloc"); mpz_init(n); return n; }
static chunk_t zalloc_chunk(size_t length, const char *name) { chunk_t chunk; chunk.len = length; chunk.ptr = alloc_bytes(length, name); memset(chunk.ptr, 0, chunk.len); return chunk; }
u_char * get_random_bits(size_t nbits, int level UNUSED, int secure UNUSED) { size_t nbytes = (nbits+7)/8; u_char *b = alloc_bytes(nbytes, "random bytes"); get_rnd_bytes(b, nbytes); return b; }
struct stack_block * stack_malloc(struct function *f, size_t bytes) { struct stack_block *ret; if ((ret = alloc_from_free_list(f, bytes)) == NULL) { ret = alloc_bytes(f, bytes); } return ret; }
/* * this routine takes two proposals and conjoins them (or) */ struct db_sa *sa_merge_proposals(struct db_sa *a, struct db_sa *b) { struct db_sa *n; unsigned int i, j, k; if (a == NULL || a->prop_conj_cnt == 0) return sa_copy_sa(b, 0); if (b == NULL || b->prop_conj_cnt == 0) return sa_copy_sa(a, 0); n = clone_thing(*a, "conjoin sa"); passert(a->prop_conj_cnt == b->prop_conj_cnt); passert(a->prop_conj_cnt == 1); n->prop_conjs = clone_bytes(n->prop_conjs, n->prop_conj_cnt * sizeof(n->prop_conjs[0]), "sa copy prop conj array"); for (i = 0; i < n->prop_conj_cnt; i++) { struct db_prop_conj *pca = &n->prop_conjs[i]; struct db_prop_conj *pcb = &b->prop_conjs[i]; passert(pca->prop_cnt == pcb->prop_cnt); passert(pca->prop_cnt == 1); pca->props = clone_bytes(pca->props, pca->prop_cnt * sizeof(pca->props[0]), "sa copy prop array"); for (j = 0; j < pca->prop_cnt; j++) { struct db_prop *pa = &pca->props[j]; struct db_prop *pb = &pcb->props[j]; struct db_trans *t; int t_cnt = (pa->trans_cnt + pb->trans_cnt); t = alloc_bytes(t_cnt * sizeof(pa->trans[0]), "sa copy trans array"); memcpy(t, pa->trans, (pa->trans_cnt) * sizeof(pa->trans[0])); memcpy(t + (pa->trans_cnt), pb->trans, (pb->trans_cnt) * sizeof(pa->trans[0])); pa->trans = t; pa->trans_cnt = t_cnt; for (k = 0; k < pa->trans_cnt; k++) clone_trans(&pa->trans[k], 0); } } n->parentSA = a->parentSA; return n; }
static __inline__ void * alloc_bytes_st (size_t size, const char *str, struct db_ops_stats *st) { void *ptr = alloc_bytes(size, str); if (ptr) { st->st_curr_cnt++; st->st_total_cnt++; if (size > st->st_maxsz) st->st_maxsz=size; } return ptr; }
pb_stream *pbs_create(int size) { pb_stream *n; void *mem; n = alloc_thing(*n, "pbs_create"); mem=alloc_bytes(size, "pbs_memory"); init_pbs(n, mem, size, "tpm_pbs"); return n; }
/* * parses the result returned by an ldap query */ static err_t parse_ldap_result(LDAP * ldap, LDAPMessage *result, chunk_t *blob) { err_t ugh = NULL; LDAPMessage * entry = ldap_first_entry(ldap, result); if (entry != NULL) { BerElement *ber = NULL; char *attr; attr = ldap_first_attribute(ldap, entry, &ber); if (attr != NULL) { struct berval **values = ldap_get_values_len(ldap, entry, attr); if (values != NULL) { if (values[0] != NULL) { blob->len = values[0]->bv_len; blob->ptr = alloc_bytes(blob->len, "ldap blob"); memcpy(blob->ptr, values[0]->bv_val, blob->len); if (values[1] != NULL) { plog("warning: more than one value was fetched from LDAP URL"); } } else { ugh = "no values in attribute"; } ldap_value_free_len(values); } else { ugh = ldap_err2string(ldap_result2error(ldap, entry, 0)); } ldap_memfree(attr); } else { ugh = ldap_err2string(ldap_result2error(ldap, entry, 0)); } ber_free(ber, 0); } else { ugh = ldap_err2string(ldap_result2error(ldap, result, 0)); } return ugh; }
/* generates a unique fingerprint of the pkcs10 request * by computing an MD5 hash over it */ void scep_generate_pkcs10_fingerprint(chunk_t pkcs10, chunk_t *fingerprint) { char buf[MD5_DIGEST_SIZE]; chunk_t digest = { buf, sizeof(buf) }; /* the fingerprint is the MD5 hash in hexadecimal format */ compute_digest(pkcs10, OID_MD5, &digest); fingerprint->len = 2*digest.len; fingerprint->ptr = alloc_bytes(fingerprint->len + 1, "fingerprint"); datatot(digest.ptr, digest.len, 16, fingerprint->ptr, fingerprint->len + 1); }
/* * UpdateRNG - Updates NSS's PRNG with user generated entropy * * pluto and rsasigkey use the NSS crypto library as its random source. * Some government Three Letter Agencies require that pluto reads additional * bits from /dev/random and feed these into the NSS RNG before drawing random * from the NSS library, despite the NSS library itself already seeding its * internal state. This process can block pluto or rsasigkey for an extended * time during startup, depending on the entropy of the system. Therefore * the default is to not perform this redundant seeding. If specifying a * value, it is recommended to specify at least 460 bits (for FIPS) or 440 * bits (for BSI). */ static void UpdateNSS_RNG(int seedbits) { SECStatus rv; int seedbytes = BYTES_FOR_BITS(seedbits); unsigned char *buf = alloc_bytes(seedbytes,"TLA seedmix"); lsw_random(seedbytes, buf); rv = PK11_RandomUpdate(buf, seedbytes); assert(rv == SECSuccess); messupn(buf, seedbytes); pfree(buf); }
/* * initialize the helpers. * * Later we will have to make provisions for helpers that have hardware * underneath them, in which case, they may be able to accept many * more requests than average. * */ void init_crypto_helpers(int nhelpers) { int i; pc_workers = NULL; pc_workers_cnt = 0; pcw_id = 1; TAILQ_INIT(&backlog); init_crypto_helper_delay(); /* find out how many CPUs there are, if nhelpers is -1 */ /* if nhelpers == 0, then we do all the work ourselves */ if (nhelpers == -1) { int ncpu_online; #if !(defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))) ncpu_online = sysconf(_SC_NPROCESSORS_ONLN); #else int mib[2], numcpu; size_t len; mib[0] = CTL_HW; mib[1] = HW_NCPU; len = sizeof(numcpu); ncpu_online = sysctl(mib, 2, &numcpu, &len, NULL, 0); #endif if (ncpu_online > 2) { nhelpers = ncpu_online - 1; } else { /* * if we have 2 CPUs or less, then create 1 helper, since * we still want to deal with head-of-queue problem. */ nhelpers = 1; } } if (nhelpers > 0) { libreswan_log("starting up %d crypto helpers", nhelpers); pc_workers = alloc_bytes(sizeof(*pc_workers) * nhelpers, "pluto crypto helpers (ignore)"); pc_workers_cnt = nhelpers; for (i = 0; i < nhelpers; i++) init_crypto_helper(&pc_workers[i], i); } else { libreswan_log( "no crypto helpers will be started; all cryptographic operations will be done inline"); } }
chunk_t hmac_pads(u_char val, unsigned int len) { chunk_t ret; unsigned int i; ret.len = len; ret.ptr = alloc_bytes(ret.len, "hmac_pad"); for (i = 0; i < len; i++) ret.ptr[i] = val; return ret; }
/* * Loads CRLs */ void load_crls(void) { struct dirent **filelist; char buf[PATH_MAX]; char *save_dir; int n; const struct lsw_conf_options *oco = lsw_init_options(); /* change directory to specified path */ save_dir = getcwd(buf, PATH_MAX); if (chdir(oco->crls_dir) == -1) { libreswan_log("Could not change to directory '%s': %d %s", oco->crls_dir, errno, strerror(errno)); } else { DBG(DBG_CONTROL, DBG_log("Changing to directory '%s'", oco->crls_dir)); n = scandir(oco->crls_dir, &filelist, (void *) filter_dotfiles, alphasort); if (n > 0) { while (n--) { chunk_t blob = empty_chunk; char *filename = filelist[n]->d_name; if (load_coded_file(filename, "crl", &blob)) { chunk_t crl_uri; crl_uri.len = 8 + strlen(oco->crls_dir) + strlen(filename); crl_uri.ptr = alloc_bytes( crl_uri.len + 1, "crl uri"); /* build CRL file URI */ snprintf((char *)crl_uri.ptr, crl_uri.len + 1, "file://%s/%s", oco->crls_dir, filename); insert_crl(blob, crl_uri); } free(filelist[n]); /* was malloced by scandir(3) */ } } free(filelist); /* was malloced by scandir(3) */ } /* restore directory path */ if (chdir(save_dir) == -1) { int e = errno; libreswan_log( "Changing back to directory '%s' failed - (%d %s)", save_dir, e, strerror(e)); } }
struct starter_conn *alloc_add_conn(struct starter_config *cfg, char *name) { struct starter_conn *conn; conn = (struct starter_conn *)alloc_bytes(sizeof(struct starter_conn),"add_conn starter_conn"); conn_default(conn, &cfg->conn_default); conn->name = clone_str(name, "add conn name"); conn->desired_state = STARTUP_IGNORE; conn->state = STATE_FAILED; TAILQ_INIT(&conn->comments); TAILQ_INSERT_TAIL(&cfg->conns, conn, link); return conn; }
/* load a coded key or certificate file with autodetection * of binary DER or base64 PEM ASN.1 formats and armored PGP format */ bool load_coded_file(const char *filename, prompt_pass_t *pass, int verbose, const char *type, chunk_t *blob, bool *pgp) { err_t ugh = NULL; FILE *fd; fd = fopen(filename, "r"); if (fd) { size_t bytes; fseek(fd, 0, SEEK_END ); blob->len = ftell(fd); if (blob->len <= 0) { if (verbose) openswan_log(" discarded %s file '%s', bad size %zu bytes", type, filename, blob->len); fclose(fd); return FALSE; } rewind(fd); blob->ptr = alloc_bytes(blob->len, type); bytes = fread(blob->ptr, 1, blob->len, fd); if(bytes != blob->len) { openswan_log(" WARNING: could not fully read certificate-blob filename '%s'\n", filename); } fclose(fd); if(verbose) { openswan_log(" loaded %s file '%s' (%zu bytes)", type, filename, bytes); } *pgp = FALSE; /* try DER format */ if (is_asn1(*blob)) { DBG(DBG_PARSING, DBG_log(" file coded in DER format"); ) return TRUE; }
/* * fetches a binary blob from a url with libcurl */ static err_t fetch_curl(char *url, chunk_t *blob) { #ifdef LIBCURL char errorbuffer[CURL_ERROR_SIZE] = ""; chunk_t response = empty_chunk; CURLcode res; /* get it with libcurl */ CURL *curl = curl_easy_init(); if (curl != NULL) { DBG(DBG_CONTROL, DBG_log("Trying cURL '%s'", url) ) curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_buffer); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer); curl_easy_setopt(curl, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, FETCH_CMD_TIMEOUT); res = curl_easy_perform(curl); if (res == CURLE_OK) { blob->len = response.len; blob->ptr = alloc_bytes(response.len, "curl blob"); memcpy(blob->ptr, response.ptr, response.len); } else { plog("fetching uri (%s) with libcurl failed: %s", url, errorbuffer); } curl_easy_cleanup(curl); /* not using freeanychunk because of realloc (no leak detective) */ curl_free(response.ptr); } return strlen(errorbuffer) > 0 ? "libcurl error" : NULL; #else /* !LIBCURL */ return "warning: not compiled with libcurl support"; #endif /* !LIBCURL */ }
/* * bundle - bundle e and n into an RFC2537-format chunk_t */ static char *base64_bundle(int e, chunk_t modulus) { /* * Pack the single-byte exponent into a byte array. */ assert(e <= 255); u_char exponent_byte = 1; chunk_t exponent = { .ptr = &exponent_byte, .len = 1, }; /* * Create the resource record. */ char *bundle; err_t err = rsa_pubkey_to_base64(exponent, modulus, &bundle); if (err) { fprintf(stderr, "%s: can't-happen bundle convert error `%s'\n", progname, err); exit(1); } return bundle; } /* UpdateRNG - Updates NSS's PRNG with user generated entropy. */ static void UpdateNSS_RNG(int seedbits) { SECStatus rv; int seedbytes = BYTES_FOR_BITS(seedbits); unsigned char *buf = alloc_bytes(seedbytes,"TLA seedmix"); getrandom(seedbytes, buf); rv = PK11_RandomUpdate(buf, seedbytes); assert(rv == SECSuccess); messupn(buf, seedbytes); pfree(buf); }