ldns_rdf * ldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port) { ldns_rdf *addr; struct sockaddr_in *data_in; struct sockaddr_in6 *data_in6; switch(sock->ss_family) { case AF_INET: data_in = (struct sockaddr_in*)sock; if (port) { *port = ntohs((uint16_t)data_in->sin_port); } addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_A, LDNS_IP4ADDRLEN, &data_in->sin_addr); break; case AF_INET6: data_in6 = (struct sockaddr_in6*)sock; if (port) { *port = ntohs((uint16_t)data_in6->sin6_port); } addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_AAAA, LDNS_IP6ADDRLEN, &data_in6->sin6_addr); break; default: if (port) { *port = 0; } return NULL; } return addr; }
ldns_rdf * ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key) { unsigned char *md5_hash; unsigned int siglen; ldns_rdf *sigdata_rdf; ldns_buffer *b64sig; b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); if (!b64sig) { return NULL; } md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign), ldns_buffer_position(to_sign), NULL); if (!md5_hash) { ldns_buffer_free(b64sig); return NULL; } RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH, (unsigned char*)ldns_buffer_begin(b64sig), &siglen, key); sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, ldns_buffer_begin(b64sig)); ldns_buffer_free(b64sig); return sigdata_rdf; }
ldns_rdf * ldns_sign_public_evp(ldns_buffer *to_sign, EVP_PKEY *key, const EVP_MD *digest_type) { unsigned int siglen; ldns_rdf *sigdata_rdf; ldns_buffer *b64sig; EVP_MD_CTX ctx; const EVP_MD *md_type; int r; siglen = 0; b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); if (!b64sig) { return NULL; } /* initializes a signing context */ md_type = digest_type; if(!md_type) { /* unknown message difest */ ldns_buffer_free(b64sig); return NULL; } EVP_MD_CTX_init(&ctx); r = EVP_SignInit(&ctx, md_type); if(r == 1) { r = EVP_SignUpdate(&ctx, (unsigned char*) ldns_buffer_begin(to_sign), ldns_buffer_position(to_sign)); } else { ldns_buffer_free(b64sig); return NULL; } if(r == 1) { r = EVP_SignFinal(&ctx, (unsigned char*) ldns_buffer_begin(b64sig), &siglen, key); } else { ldns_buffer_free(b64sig); return NULL; } if(r != 1) { ldns_buffer_free(b64sig); return NULL; } /* unfortunately, OpenSSL output is differenct from DNS DSA format */ if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) { sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen); } else { /* ok output for other types is the same */ sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, ldns_buffer_begin(b64sig)); } ldns_buffer_free(b64sig); EVP_MD_CTX_cleanup(&ctx); return sigdata_rdf; }
ldns_rdf * ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key) { unsigned char *sha1_hash; unsigned int siglen; ldns_rdf *sigdata_rdf; ldns_buffer *b64sig; int result; siglen = 0; b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); if (!b64sig) { return NULL; } sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign), ldns_buffer_position(to_sign), NULL); if (!sha1_hash) { ldns_buffer_free(b64sig); return NULL; } result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH, (unsigned char*)ldns_buffer_begin(b64sig), &siglen, key); if (result != 1) { ldns_buffer_free(b64sig); return NULL; } sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, ldns_buffer_begin(b64sig)); ldns_buffer_free(b64sig); /* can't free this buffer ?? */ return sigdata_rdf; }
/** * Sign data with DSA * * \param[in] to_sign The ldns_buffer containing raw data that is * to be signed * \param[in] key The DSA key structure to sign with * \return ldns_rdf for the RRSIG ldns_rr */ ldns_rdf * ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key) { unsigned char *sha1_hash; ldns_rdf *sigdata_rdf; ldns_buffer *b64sig; DSA_SIG *sig; uint8_t *data; size_t pad; b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); if (!b64sig) { return NULL; } sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign), ldns_buffer_position(to_sign), NULL); if (!sha1_hash) { ldns_buffer_free(b64sig); return NULL; } sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key); if(!sig) { ldns_buffer_free(b64sig); return NULL; } data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH); if(!data) { ldns_buffer_free(b64sig); DSA_SIG_free(sig); return NULL; } data[0] = 1; pad = 20 - (size_t) BN_num_bytes(sig->r); if (pad > 0) { memset(data + 1, 0, pad); } BN_bn2bin(sig->r, (unsigned char *) (data + 1) + pad); pad = 20 - (size_t) BN_num_bytes(sig->s); if (pad > 0) { memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad); } BN_bn2bin(sig->s, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad)); sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, 1 + 2 * SHA_DIGEST_LENGTH, data); ldns_buffer_free(b64sig); LDNS_FREE(data); DSA_SIG_free(sig); return sigdata_rdf; }
ldns_status ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name, uint16_t port, ldns_dane_transport transport) { char buf[LDNS_MAX_DOMAINLEN]; size_t s; assert(tlsa_owner != NULL); assert(name != NULL); assert(ldns_rdf_get_type(name) == LDNS_RDF_TYPE_DNAME); s = (size_t)snprintf(buf, LDNS_MAX_DOMAINLEN, "X_%d", (int)port); buf[0] = (char)(s - 1); switch(transport) { case LDNS_DANE_TRANSPORT_TCP: s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_tcp"); break; case LDNS_DANE_TRANSPORT_UDP: s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_udp"); break; case LDNS_DANE_TRANSPORT_SCTP: s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\005_sctp"); break; default: return LDNS_STATUS_DANE_UNKNOWN_TRANSPORT; } if (s + ldns_rdf_size(name) > LDNS_MAX_DOMAINLEN) { return LDNS_STATUS_DOMAINNAME_OVERFLOW; } memcpy(buf + s, ldns_rdf_data(name), ldns_rdf_size(name)); *tlsa_owner = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, s + ldns_rdf_size(name), buf); if (*tlsa_owner == NULL) { return LDNS_STATUS_MEM_ERR; } return LDNS_STATUS_OK; }
static ldns_status ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size, const char *key_data, ldns_rdf *key_name_rdf, ldns_rdf *fudge_rdf, ldns_rdf *algorithm_rdf, ldns_rdf *time_signed_rdf, ldns_rdf *error_rdf, ldns_rdf *other_data_rdf, ldns_rdf *orig_mac_rdf, int tsig_timers_only) { ldns_status status; char *wireformat; int wiresize; unsigned char *mac_bytes = NULL; unsigned char *key_bytes = NULL; int key_size; const EVP_MD *digester; char *algorithm_name = NULL; unsigned int md_len = EVP_MAX_MD_SIZE; ldns_rdf *result = NULL; ldns_buffer *data_buffer = NULL; ldns_rdf *canonical_key_name_rdf = NULL; ldns_rdf *canonical_algorithm_rdf = NULL; if (key_name_rdf == NULL || algorithm_rdf == NULL) { return LDNS_STATUS_NULL; } canonical_key_name_rdf = ldns_rdf_clone(key_name_rdf); if (canonical_key_name_rdf == NULL) { return LDNS_STATUS_MEM_ERR; } canonical_algorithm_rdf = ldns_rdf_clone(algorithm_rdf); if (canonical_algorithm_rdf == NULL) { ldns_rdf_deep_free(canonical_key_name_rdf); return LDNS_STATUS_MEM_ERR; } /* * prepare the digestable information */ data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); if (!data_buffer) { status = LDNS_STATUS_MEM_ERR; goto clean; } /* if orig_mac is not NULL, add it too */ if (orig_mac_rdf) { (void) ldns_rdf2buffer_wire(data_buffer, orig_mac_rdf); } ldns_buffer_write(data_buffer, pkt_wire, pkt_wire_size); if (!tsig_timers_only) { ldns_dname2canonical(canonical_key_name_rdf); (void)ldns_rdf2buffer_wire(data_buffer, canonical_key_name_rdf); ldns_buffer_write_u16(data_buffer, LDNS_RR_CLASS_ANY); ldns_buffer_write_u32(data_buffer, 0); ldns_dname2canonical(canonical_algorithm_rdf); (void)ldns_rdf2buffer_wire(data_buffer, canonical_algorithm_rdf); } (void)ldns_rdf2buffer_wire(data_buffer, time_signed_rdf); (void)ldns_rdf2buffer_wire(data_buffer, fudge_rdf); if (!tsig_timers_only) { (void)ldns_rdf2buffer_wire(data_buffer, error_rdf); (void)ldns_rdf2buffer_wire(data_buffer, other_data_rdf); } wireformat = (char *) data_buffer->_data; wiresize = (int) ldns_buffer_position(data_buffer); algorithm_name = ldns_rdf2str(algorithm_rdf); if(!algorithm_name) { status = LDNS_STATUS_MEM_ERR; goto clean; } /* prepare the key */ key_bytes = LDNS_XMALLOC(unsigned char, ldns_b64_pton_calculate_size(strlen(key_data))); if(!key_bytes) { status = LDNS_STATUS_MEM_ERR; goto clean; } key_size = ldns_b64_pton(key_data, key_bytes, ldns_b64_pton_calculate_size(strlen(key_data))); if (key_size < 0) { status = LDNS_STATUS_INVALID_B64; goto clean; } /* hmac it */ /* 2 spare bytes for the length */ mac_bytes = LDNS_XMALLOC(unsigned char, md_len+2); if(!mac_bytes) { status = LDNS_STATUS_MEM_ERR; goto clean; } memset(mac_bytes, 0, md_len+2); digester = ldns_digest_function(algorithm_name); if (digester) { (void) HMAC(digester, key_bytes, key_size, (void *)wireformat, (size_t) wiresize, mac_bytes + 2, &md_len); ldns_write_uint16(mac_bytes, md_len); result = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16_DATA, md_len + 2, mac_bytes); } else { status = LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; goto clean; } *tsig_mac = result; status = LDNS_STATUS_OK; clean: LDNS_FREE(mac_bytes); LDNS_FREE(key_bytes); LDNS_FREE(algorithm_name); ldns_buffer_free(data_buffer); ldns_rdf_deep_free(canonical_algorithm_rdf); ldns_rdf_deep_free(canonical_key_name_rdf); return status; }