isc_result_t dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx, dst_key_t **keyp, isc_region_t *intoken) { dst_key_t *key; isc_result_t result; REQUIRE(gssctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC, 0, dns_rdataclass_in, 0, mctx); if (key == NULL) return (ISC_R_NOMEMORY); if (intoken != NULL) { /* * Keep the token for use by external ssu rules. They may need * to examine the PAC in the kerberos ticket. */ RETERR(isc_buffer_allocate(key->mctx, &key->key_tkeytoken, intoken->length)); RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken)); } key->keydata.gssctx = gssctx; *keyp = key; result = ISC_R_SUCCESS; out: return result; }
isc_result_t dst_key_buildinternal(dns_name_t *name, unsigned int alg, unsigned int bits, unsigned int flags, unsigned int protocol, dns_rdataclass_t rdclass, void *data, isc_mem_t *mctx, dst_key_t **keyp) { dst_key_t *key; isc_result_t result; REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(dns_name_isabsolute(name)); REQUIRE(mctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); REQUIRE(data != NULL); CHECKALG(alg); key = get_key_struct(name, alg, flags, protocol, bits, rdclass, 0, mctx); if (key == NULL) return (ISC_R_NOMEMORY); key->keydata.generic = data; result = computeid(key); if (result != ISC_R_SUCCESS) { dst_key_free(&key); return (result); } *keyp = key; return (ISC_R_SUCCESS); }
isc_result_t dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags, unsigned int protocol, dns_rdataclass_t rdclass, isc_mem_t *mctx, const char *keystr, dst_key_t **keyp) { isc_result_t result; dst_key_t *key; REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(keyp != NULL && *keyp == NULL); if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL) return (DST_R_UNSUPPORTEDALG); if (dst_t_func[alg]->restore == NULL) return (ISC_R_NOTIMPLEMENTED); key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); if (key == NULL) return (ISC_R_NOMEMORY); result = (dst_t_func[alg]->restore)(key, keystr); if (result == ISC_R_SUCCESS) *keyp = key; else dst_key_free(&key); return (result); }
isc_result_t dst_key_generate2(dns_name_t *name, unsigned int alg, unsigned int bits, unsigned int param, unsigned int flags, unsigned int protocol, dns_rdataclass_t rdclass, isc_mem_t *mctx, dst_key_t **keyp, void (*callback)(int)) { dst_key_t *key; isc_result_t ret; REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(dns_name_isabsolute(name)); REQUIRE(mctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); CHECKALG(alg); key = get_key_struct(name, alg, flags, protocol, bits, rdclass, 0, mctx); if (key == NULL) return (ISC_R_NOMEMORY); if (bits == 0) { /*%< NULL KEY */ key->key_flags |= DNS_KEYTYPE_NOKEY; *keyp = key; return (ISC_R_SUCCESS); } if (key->func->generate == NULL) { dst_key_free(&key); return (DST_R_UNSUPPORTEDALG); } ret = key->func->generate(key, param, callback); if (ret != ISC_R_SUCCESS) { dst_key_free(&key); return (ret); } ret = computeid(key); if (ret != ISC_R_SUCCESS) { dst_key_free(&key); return (ret); } *keyp = key; return (ISC_R_SUCCESS); }
isc_result_t dst_key_fromgssapi(dns_name_t *name, void *opaque, isc_mem_t *mctx, dst_key_t **keyp) { dst_key_t *key; REQUIRE(opaque != NULL); REQUIRE(keyp != NULL && *keyp == NULL); key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC, 0, dns_rdataclass_in, mctx); if (key == NULL) return (ISC_R_NOMEMORY); key->opaque = opaque; *keyp = key; return (ISC_R_SUCCESS); }
isc_result_t dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx, dst_key_t **keyp) { dst_key_t *key; REQUIRE(gssctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC, 0, dns_rdataclass_in, mctx); if (key == NULL) return (ISC_R_NOMEMORY); key->keydata.gssctx = gssctx; *keyp = key; return (ISC_R_SUCCESS); }
isc_result_t dst_key_fromlabel(dns_name_t *name, int alg, unsigned int flags, unsigned int protocol, dns_rdataclass_t rdclass, const char *engine, const char *label, const char *pin, isc_mem_t *mctx, dst_key_t **keyp) { dst_key_t *key; isc_result_t result; REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(dns_name_isabsolute(name)); REQUIRE(mctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); REQUIRE(label != NULL); CHECKALG(alg); key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); if (key == NULL) return (ISC_R_NOMEMORY); if (key->func->fromlabel == NULL) { dst_key_free(&key); return (DST_R_UNSUPPORTEDALG); } result = key->func->fromlabel(key, engine, label, pin); if (result != ISC_R_SUCCESS) { dst_key_free(&key); return (result); } result = computeid(key); if (result != ISC_R_SUCCESS) { dst_key_free(&key); return (result); } *keyp = key; return (ISC_R_SUCCESS); }
static isc_result_t frombuffer(dns_name_t *name, unsigned int alg, unsigned int flags, unsigned int protocol, dns_rdataclass_t rdclass, isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) { dst_key_t *key; isc_result_t ret; REQUIRE(dns_name_isabsolute(name)); REQUIRE(source != NULL); REQUIRE(mctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); if (key == NULL) return (ISC_R_NOMEMORY); if (isc_buffer_remaininglength(source) > 0) { ret = algorithm_status(alg); if (ret != ISC_R_SUCCESS) { dst_key_free(&key); return (ret); } if (key->func->fromdns == NULL) { dst_key_free(&key); return (DST_R_UNSUPPORTEDALG); } ret = key->func->fromdns(key, source); if (ret != ISC_R_SUCCESS) { dst_key_free(&key); return (ret); } } *keyp = key; return (ISC_R_SUCCESS); }
isc_result_t dst_key_fromnamedfile(const char *filename, const char *dirname, int type, isc_mem_t *mctx, dst_key_t **keyp) { isc_result_t result; dst_key_t *pubkey = NULL, *key = NULL; char *newfilename = NULL; int newfilenamelen = 0; isc_lex_t *lex = NULL; REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(filename != NULL); REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0); REQUIRE(mctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); /* If an absolute path is specified, don't use the key directory */ #ifndef WIN32 if (filename[0] == '/') dirname = NULL; #else /* WIN32 */ if (filename[0] == '/' || filename[0] == '\\') dirname = NULL; #endif newfilenamelen = strlen(filename) + 5; if (dirname != NULL) newfilenamelen += strlen(dirname) + 1; newfilename = isc_mem_get(mctx, newfilenamelen); if (newfilename == NULL) return (ISC_R_NOMEMORY); result = addsuffix(newfilename, newfilenamelen, dirname, filename, ".key"); INSIST(result == ISC_R_SUCCESS); result = dst_key_read_public(newfilename, type, mctx, &pubkey); isc_mem_put(mctx, newfilename, newfilenamelen); newfilename = NULL; RETERR(result); if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC || (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) { result = computeid(pubkey); if (result != ISC_R_SUCCESS) { dst_key_free(&pubkey); return (result); } *keyp = pubkey; return (ISC_R_SUCCESS); } result = algorithm_status(pubkey->key_alg); if (result != ISC_R_SUCCESS) { dst_key_free(&pubkey); return (result); } key = get_key_struct(pubkey->key_name, pubkey->key_alg, pubkey->key_flags, pubkey->key_proto, 0, pubkey->key_class, pubkey->key_ttl, mctx); if (key == NULL) { dst_key_free(&pubkey); return (ISC_R_NOMEMORY); } if (key->func->parse == NULL) RETERR(DST_R_UNSUPPORTEDALG); newfilenamelen = strlen(filename) + 9; if (dirname != NULL) newfilenamelen += strlen(dirname) + 1; newfilename = isc_mem_get(mctx, newfilenamelen); if (newfilename == NULL) RETERR(ISC_R_NOMEMORY); result = addsuffix(newfilename, newfilenamelen, dirname, filename, ".private"); INSIST(result == ISC_R_SUCCESS); RETERR(isc_lex_create(mctx, 1500, &lex)); RETERR(isc_lex_openfile(lex, newfilename)); isc_mem_put(mctx, newfilename, newfilenamelen); RETERR(key->func->parse(key, lex, pubkey)); isc_lex_destroy(&lex); RETERR(computeid(key)); if (pubkey->key_id != key->key_id) RETERR(DST_R_INVALIDPRIVATEKEY); dst_key_free(&pubkey); *keyp = key; return (ISC_R_SUCCESS); out: if (pubkey != NULL) dst_key_free(&pubkey); if (newfilename != NULL) isc_mem_put(mctx, newfilename, newfilenamelen); if (lex != NULL) isc_lex_destroy(&lex); if (key != NULL) dst_key_free(&key); return (result); }
int main(void){ int i; struct timeval tvs,tve; void *keys=get_key_struct(); int ok=1; fprintf(stderr,"FFdecsa 1.0: testing correctness and speed\n"); /* begin correctness testing */ set_control_words(keys,test_invalid_key,test_1_key); memcpy(onebuf,test_1_encrypted,188); cluster[0]=onebuf;cluster[1]=onebuf+188;cluster[2]=NULL; decrypt_packets(keys,cluster); ok*=compare(onebuf,test_1_expected,188,0); set_control_words(keys,test_2_key,test_invalid_key); memcpy(onebuf,test_2_encrypted,188); cluster[0]=onebuf;cluster[1]=onebuf+188;cluster[2]=NULL; decrypt_packets(keys,cluster); ok*=compare(onebuf,test_2_expected,188,0); set_control_words(keys,test_3_key,test_invalid_key); memcpy(onebuf,test_3_encrypted,188); cluster[0]=onebuf;cluster[1]=onebuf+188;cluster[2]=NULL; decrypt_packets(keys,cluster); ok*=compare(onebuf,test_3_expected,188,0); set_control_words(keys,test_p_10_0_key,test_invalid_key); memcpy(onebuf,test_p_10_0_encrypted,188); cluster[0]=onebuf;cluster[1]=onebuf+188;cluster[2]=NULL; decrypt_packets(keys,cluster); ok*=compare(onebuf,test_p_10_0_expected,188,0); set_control_words(keys,test_p_1_6_key,test_invalid_key); memcpy(onebuf,test_p_1_6_encrypted,188); cluster[0]=onebuf;cluster[1]=onebuf+188;cluster[2]=NULL; decrypt_packets(keys,cluster); ok*=compare(onebuf,test_p_1_6_expected,188,0); /* begin speed testing */ #if 0 // test on short packets #define s_encrypted test_p_1_6_encrypted #define s_key_e test_p_1_6_key #define s_key_o test_invalid_key #define s_expected test_p_1_6_expected #else //test on full packets #define s_encrypted test_2_encrypted #define s_key_e test_2_key #define s_key_o test_invalid_key #define s_expected test_2_expected #endif for(i=0;i<TS_PKTS_FOR_TEST;i++){ memcpy(&megabuf[188*i],s_encrypted,188); } // test that packets are not shuffled around // so, let's put an undecryptable packet somewhere in the middle (we will use a wrong key) #define noONE_POISONED_PACKET #ifdef ONE_POISONED_PACKET memcpy(&megabuf[188*(TS_PKTS_FOR_TEST*2/3)],test_3_encrypted,188); #endif // start decryption set_control_words(keys,s_key_e,s_key_o); gettimeofday(&tvs,NULL); #if 0 // force one by one for(i=0;i<TS_PKTS_FOR_TEST;i++){ cluster[0]=megabuf+188*i;cluster[1]=onebuf+188*i+188;cluster[2]=NULL; decrypt_packets(keys,cluster); } #else { int done=0; while(done<TS_PKTS_FOR_TEST){ //fprintf(stderr,"done=%i\n",done); cluster[0]=megabuf+188*done;cluster[1]=megabuf+188*TS_PKTS_FOR_TEST;cluster[2]=NULL; done+=decrypt_packets(keys,cluster); } } #endif gettimeofday(&tve,NULL); //end decryption fprintf(stderr,"speed=%f Mbit/s\n",(184*TS_PKTS_FOR_TEST*8)/((tve.tv_sec-tvs.tv_sec)+1e-6*(tve.tv_usec-tvs.tv_usec))/1000000); fprintf(stderr,"speed=%f pkts/s\n",TS_PKTS_FOR_TEST/((tve.tv_sec-tvs.tv_sec)+1e-6*(tve.tv_usec-tvs.tv_usec))); // this packet couldn't be decrypted correctly #ifdef ONE_POISONED_PACKET compare(megabuf+188*(TS_PKTS_FOR_TEST*2/3),test_3_expected,188,0); /* will fail because we used a wrong key */ #endif // these should be ok ok*=compare(megabuf,s_expected,188,0); ok*=compare(megabuf+188*511,s_expected,188,0); ok*=compare(megabuf+188*512,s_expected,188,0); ok*=compare(megabuf+188*319,s_expected,188,0); ok*=compare(megabuf+188*(TS_PKTS_FOR_TEST-1),s_expected,188,0); for(i=0;i<TS_PKTS_FOR_TEST;i++){ if(!compare(megabuf+188*i,s_expected,188,1)){ fprintf(stderr,"FAILED COMPARISON OF PACKET %10i\n",i); ok=0; }; } return ok ? 0 : 10; }
isc_result_t dst_key_fromnamedfile(const char *filename, int type, isc_mem_t *mctx, dst_key_t **keyp) { isc_result_t result; dst_key_t *pubkey = NULL, *key = NULL; dns_keytag_t id; char *newfilename = NULL; int newfilenamelen = 0; isc_lex_t *lex = NULL; REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(filename != NULL); REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0); REQUIRE(mctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); newfilenamelen = strlen(filename) + 5; newfilename = isc_mem_get(mctx, newfilenamelen); if (newfilename == NULL) return (ISC_R_NOMEMORY); result = addsuffix(newfilename, newfilenamelen, filename, ".key"); INSIST(result == ISC_R_SUCCESS); result = dst_key_read_public(newfilename, type, mctx, &pubkey); isc_mem_put(mctx, newfilename, newfilenamelen); newfilename = NULL; if (result != ISC_R_SUCCESS) return (result); if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC || (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) { result = computeid(pubkey); if (result != ISC_R_SUCCESS) { dst_key_free(&pubkey); return (result); } *keyp = pubkey; return (ISC_R_SUCCESS); } result = algorithm_status(pubkey->key_alg); if (result != ISC_R_SUCCESS) { dst_key_free(&pubkey); return (result); } key = get_key_struct(pubkey->key_name, pubkey->key_alg, pubkey->key_flags, pubkey->key_proto, 0, pubkey->key_class, mctx); id = pubkey->key_id; dst_key_free(&pubkey); if (key == NULL) return (ISC_R_NOMEMORY); if (key->func->parse == NULL) RETERR(DST_R_UNSUPPORTEDALG); newfilenamelen = strlen(filename) + 9; newfilename = isc_mem_get(mctx, newfilenamelen); if (newfilename == NULL) RETERR(ISC_R_NOMEMORY); result = addsuffix(newfilename, newfilenamelen, filename, ".private"); INSIST(result == ISC_R_SUCCESS); RETERR(isc_lex_create(mctx, 1500, &lex)); RETERR(isc_lex_openfile(lex, newfilename)); isc_mem_put(mctx, newfilename, newfilenamelen); RETERR(key->func->parse(key, lex)); isc_lex_destroy(&lex); RETERR(computeid(key)); if (id != key->key_id) RETERR(DST_R_INVALIDPRIVATEKEY); *keyp = key; return (ISC_R_SUCCESS); out: if (newfilename != NULL) isc_mem_put(mctx, newfilename, newfilenamelen); if (lex != NULL) isc_lex_destroy(&lex); dst_key_free(&key); return (result); }