dnssec.c

Go to the documentation of this file.
00001 /* 
00002  * dnssec.c
00003  *
00004  * contains the cryptographic function needed for DNSSEC
00005  * The crypto library used is openssl
00006  *
00007  * (c) NLnet Labs, 2004-2006
00008  * a Net::DNS like library for C
00009  *
00010  * See the file LICENSE for the license
00011  */
00012 
00013 #include <ldns/config.h>
00014 
00015 #include <ldns/ldns.h>
00016 
00017 #include <strings.h>
00018 #include <time.h>
00019 
00020 #ifdef HAVE_SSL
00021 /* this entire file is rather useless when you don't have
00022  * crypto...
00023  */
00024 #include <openssl/ssl.h>
00025 #include <openssl/rand.h>
00026 #include <openssl/err.h>
00027 #include <openssl/md5.h>
00028 
00029 /* used only on the public key RR */
00030 uint16_t
00031 ldns_calc_keytag(const ldns_rr *key)
00032 {
00033         unsigned int i;
00034         uint32_t ac32;
00035         uint16_t ac16;
00036         
00037         ldns_buffer *keybuf;
00038         size_t keysize;
00039 
00040         if (!key) {
00041                 return 0;
00042         }
00043 
00044         ac32 = 0;
00045         if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY &&
00046             ldns_rr_get_type(key) != LDNS_RR_TYPE_KEY
00047             ) {
00048                 return 0;
00049         }
00050 
00051         /* rdata to buf - only put the rdata in a buffer */
00052         keybuf = ldns_buffer_new(LDNS_MIN_BUFLEN); /* grows */
00053         if (!keybuf) {
00054                 return 0;
00055         }
00056         (void)ldns_rr_rdata2buffer_wire(keybuf, key);
00057         /* the current pos in the buffer is the keysize */
00058         keysize= ldns_buffer_position(keybuf);
00059 
00060         /* look at the algorithm field, copied from 2535bis */
00061         if (ldns_rdf2native_int8(ldns_rr_rdf(key, 2)) == LDNS_RSAMD5) {
00062                 if (keysize > 4) {
00063                         ldns_buffer_read_at(keybuf, keysize - 3, &ac16, 2);
00064                 }
00065                 ldns_buffer_free(keybuf);
00066                 ac16 = ntohs(ac16);
00067                 return (uint16_t) ac16;
00068         } else {
00069                 for (i = 0; (size_t)i < keysize; ++i) {
00070                         ac32 += (i & 1) ? *ldns_buffer_at(keybuf, i) : 
00071                                 *ldns_buffer_at(keybuf, i) << 8;
00072                 }
00073                 ldns_buffer_free(keybuf);
00074                 ac32 += (ac32 >> 16) & 0xFFFF;
00075 /*printf("RETURNING %u\n", (uint16_t) (ac32 & 0xFFFF));*/
00076                 return (uint16_t) (ac32 & 0xFFFF);
00077         }
00078 }
00079 
00080 ldns_status
00081 ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, ldns_rr_list *keys, 
00082                 ldns_rr_list *good_keys)
00083 {
00084         uint16_t i;
00085         bool valid;
00086         ldns_status verify_result = LDNS_STATUS_ERR;
00087 
00088         if (!rrset || !rrsig || !keys) {
00089                 return LDNS_STATUS_ERR;
00090         }
00091 
00092         valid = false;
00093 
00094         if (ldns_rr_list_rr_count(rrset) < 1) {
00095                 return LDNS_STATUS_ERR;
00096         }
00097 
00098         if (ldns_rr_list_rr_count(rrsig) < 1) {
00099                 return LDNS_STATUS_CRYPTO_NO_RRSIG;
00100         }
00101         
00102         if (ldns_rr_list_rr_count(keys) < 1) {
00103                 verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
00104         } else {
00105                 for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
00106 
00107                         if (ldns_verify_rrsig_keylist(rrset,
00108                                         ldns_rr_list_rr(rrsig, i),
00109                                         keys, good_keys) == LDNS_STATUS_OK) {
00110                                 verify_result = LDNS_STATUS_OK;
00111                         }
00112                 }
00113         }
00114         return verify_result;
00115 }
00116 
00117 ldns_status
00118 ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf, 
00119                 ldns_buffer *key_buf, uint8_t algo)
00120 {
00121                 /* check for right key */
00122                 switch(algo) {
00123                         case LDNS_DSA:
00124                                 return ldns_verify_rrsig_dsa(rawsig_buf, verify_buf, key_buf);
00125                                 break;
00126                         case LDNS_RSASHA1:
00127                                 return ldns_verify_rrsig_rsasha1(rawsig_buf, verify_buf, key_buf);
00128                                 break;
00129                         case LDNS_RSAMD5:
00130                                 return ldns_verify_rrsig_rsamd5(rawsig_buf, verify_buf, key_buf);
00131                                 break;
00132                         default:
00133                                 /* do you know this alg?! */
00134                                 return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
00135                 }
00136 }
00137 
00138 /* Post 1.0 TODO: next 2 functions contain a lot of similar code */
00139 /* 
00140  * to verify:
00141  * - create the wire fmt of the b64 key rdata
00142  * - create the wire fmt of the sorted rrset
00143  * - create the wire fmt of the b64 sig rdata
00144  * - create the wire fmt of the sig without the b64 rdata
00145  * - cat the sig data (without b64 rdata) to the rrset
00146  * - verify the rrset+sig, with the b64 data and the b64 key data
00147  */
00148 ldns_status
00149 ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr_list *keys, 
00150                 ldns_rr_list *good_keys)
00151 {
00152         ldns_buffer *rawsig_buf;
00153         ldns_buffer *verify_buf;
00154         ldns_buffer *key_buf;
00155         uint32_t orig_ttl;
00156         uint16_t i;
00157         uint8_t sig_algo;
00158         ldns_status result;
00159         ldns_rr *current_key;
00160         ldns_rr_list *rrset_clone;
00161         ldns_rr_list *validkeys;
00162         time_t now, inception, expiration;
00163         uint8_t label_count;
00164         ldns_rdf *wildcard_name;
00165         ldns_rdf *wildcard_chopped;
00166         ldns_rdf *wildcard_chopped_tmp;
00167 
00168 
00169         if (!rrset) {
00170                 return LDNS_STATUS_ERR;
00171         }
00172 
00173         validkeys = ldns_rr_list_new();
00174         if (!validkeys) {
00175                 return LDNS_STATUS_MEM_ERR;
00176         }
00177         
00178         /* canonicalize the sig */
00179         ldns_dname2canonical(ldns_rr_owner(rrsig));
00180         
00181         /* clone the rrset so that we can fiddle with it */
00182         rrset_clone = ldns_rr_list_clone(rrset);
00183 
00184         /* check if the typecovered is equal to the type checked */
00185         if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rrsig)) !=
00186                         ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0))) {
00187                 return LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR;
00188         }
00189         
00190         /* create the buffers which will certainly hold the raw data */
00191         rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00192         verify_buf  = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00193         
00194         sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1));
00195         result = LDNS_STATUS_ERR;
00196 
00197         /* check the signature time stamps */
00198         inception = ldns_rdf2native_time_t(ldns_rr_rrsig_inception(rrsig));
00199         expiration = ldns_rdf2native_time_t(ldns_rr_rrsig_expiration(rrsig));
00200         now = time(NULL);
00201 
00202         if (expiration - inception < 0) {
00203                 /* bad sig, expiration before inception?? Tsssg */
00204                 ldns_buffer_free(rawsig_buf);
00205                 ldns_buffer_free(verify_buf);
00206                 return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION;
00207         }
00208         if (now - inception < 0) {
00209                 /* bad sig, inception date has passed */
00210                 ldns_buffer_free(rawsig_buf);
00211                 ldns_buffer_free(verify_buf);
00212                 return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED;
00213         }
00214         if (expiration - now < 0) {
00215                 /* bad sig, expiration date has passed */
00216                 ldns_buffer_free(rawsig_buf);
00217                 ldns_buffer_free(verify_buf);
00218                 return LDNS_STATUS_CRYPTO_SIG_EXPIRED;
00219         }
00220         
00221         /* create a buffer with b64 signature rdata */
00222         if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) {
00223                 ldns_buffer_free(rawsig_buf);
00224                 ldns_buffer_free(verify_buf);
00225                 return LDNS_STATUS_MEM_ERR;
00226         }
00227 
00228         orig_ttl = ldns_rdf2native_int32( ldns_rr_rdf(rrsig, 3));
00229         label_count = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 2));
00230 
00231         /* reset the ttl in the rrset with the orig_ttl from the sig */
00232         /* and update owner name if it was wildcard */
00233         for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
00234                 if (label_count < 
00235                         ldns_dname_label_count(
00236                                 ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) {
00237                         (void) ldns_str2rdf_dname(&wildcard_name, "*");
00238                         wildcard_chopped = ldns_rdf_clone(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)));
00239                         while (label_count < ldns_dname_label_count(wildcard_chopped)) {
00240                                 wildcard_chopped_tmp = ldns_dname_left_chop(wildcard_chopped);
00241                                 ldns_rdf_deep_free(wildcard_chopped);
00242                                 wildcard_chopped = wildcard_chopped_tmp;
00243                         }
00244                         (void) ldns_dname_cat(wildcard_name, wildcard_chopped);
00245                         ldns_rdf_deep_free(wildcard_chopped);
00246                         ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)));
00247                         ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), 
00248                                         wildcard_name);
00249                                         
00250                 }
00251                 ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), orig_ttl);
00252                 /* convert to lowercase */
00253                 ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
00254         }
00255 
00256         /* sort the rrset in canonical order  */
00257         ldns_rr_list_sort(rrset_clone);
00258 
00259         /* put the signature rr (without the b64) to the verify_buf */
00260         if (ldns_rrsig2buffer_wire(verify_buf, rrsig) != LDNS_STATUS_OK) {
00261                 ldns_buffer_free(rawsig_buf);
00262                 ldns_buffer_free(verify_buf);
00263                 return LDNS_STATUS_MEM_ERR;
00264         }
00265 
00266         /* add the rrset in verify_buf */
00267         if (ldns_rr_list2buffer_wire(verify_buf, rrset_clone) != LDNS_STATUS_OK) {
00268                 ldns_buffer_free(rawsig_buf);
00269                 ldns_buffer_free(verify_buf);
00270                 return LDNS_STATUS_MEM_ERR;
00271         }
00272 
00273         for(i = 0; i < ldns_rr_list_rr_count(keys); i++) {
00274                 current_key = ldns_rr_list_rr(keys, i);
00275                 /* before anything, check if the keytags match */
00276                 if (ldns_calc_keytag(current_key) ==
00277                     ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig))) {
00278                         key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00279                         
00280                         /* put the key-data in a buffer, that's the third rdf, with
00281                          * the base64 encoded key data */
00282                         if (ldns_rdf2buffer_wire(key_buf,
00283                                         ldns_rr_rdf(current_key, 3)) != LDNS_STATUS_OK) {
00284                                 ldns_buffer_free(rawsig_buf);
00285                                 ldns_buffer_free(verify_buf);
00286                                 /* returning is bad might screw up good keys later in the list
00287                                    what to do? */
00288                                 return LDNS_STATUS_MEM_ERR;
00289                         }
00290 
00291                         /* check for right key */
00292                         if (sig_algo == ldns_rdf2native_int8(ldns_rr_rdf(current_key, 
00293                                                         2))) {
00294                                 result = ldns_verify_rrsig_buffers(rawsig_buf, 
00295                                                 verify_buf, key_buf, sig_algo);
00296                         } else {
00297                                 /* There is no else here ???? */
00298                         }
00299                         
00300                         ldns_buffer_free(key_buf); 
00301 
00302                         if (result == LDNS_STATUS_OK) {
00303                                 /* one of the keys has matched, don't break
00304                                  * here, instead put the 'winning' key in
00305                                  * the validkey list and return the list 
00306                                  * later */
00307                                 if (!ldns_rr_list_push_rr(validkeys, current_key)) {
00308                                         /* couldn't push the key?? */
00309                                         ldns_buffer_free(rawsig_buf);
00310                                         ldns_buffer_free(verify_buf);
00311                                         return LDNS_STATUS_MEM_ERR;
00312                                 }
00313                         } 
00314                 } else {
00315                         result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
00316                 }
00317         }
00318 
00319         /* no longer needed */
00320         ldns_rr_list_deep_free(rrset_clone);
00321         ldns_buffer_free(rawsig_buf);
00322         ldns_buffer_free(verify_buf);
00323         if (ldns_rr_list_rr_count(validkeys) == 0) {
00324                 /* no keys were added, return last error */
00325                 ldns_rr_list_deep_free(validkeys); 
00326                 return result;
00327         } else {
00328                 ldns_rr_list_cat(good_keys, validkeys);
00329                 ldns_rr_list_free(validkeys);
00330                 return LDNS_STATUS_OK;
00331         }
00332 }
00333 
00334 ldns_status
00335 ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key)
00336 {
00337         ldns_buffer *rawsig_buf;
00338         ldns_buffer *verify_buf;
00339         ldns_buffer *key_buf;
00340         uint32_t orig_ttl;
00341         uint16_t i;
00342         uint8_t sig_algo;
00343         uint16_t label_count;
00344         ldns_status result;
00345         ldns_rr_list *rrset_clone;
00346         time_t now, inception, expiration;
00347         ldns_rdf *wildcard_name;
00348         ldns_rdf *wildcard_chopped;
00349         ldns_rdf *wildcard_chopped_tmp;
00350 
00351 
00352         if (!rrset) {
00353                 return LDNS_STATUS_NO_DATA;
00354         }
00355 
00356         /* lowercase the rrsig owner name */
00357         ldns_dname2canonical(ldns_rr_owner(rrsig));
00358 
00359         /* check the signature time stamps */
00360         inception = ldns_rdf2native_time_t(ldns_rr_rrsig_inception(rrsig));
00361         expiration = ldns_rdf2native_time_t(ldns_rr_rrsig_expiration(rrsig));
00362         now = time(NULL);
00363 
00364         if (expiration - inception < 0) {
00365                 /* bad sig, expiration before inception?? Tsssg */
00366                 return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION;
00367         }
00368         if (now - inception < 0) {
00369                 /* bad sig, inception date has passed */
00370                 return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED;
00371         }
00372 
00373         if (expiration - now < 0) {
00374                 /* bad sig, expiration date has passed */
00375                 return LDNS_STATUS_CRYPTO_SIG_EXPIRED;
00376         }
00377         /* clone the rrset so that we can fiddle with it */
00378         rrset_clone = ldns_rr_list_clone(rrset);
00379         
00380         /* create the buffers which will certainly hold the raw data */
00381         rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00382         verify_buf  = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00383         
00384         sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1));
00385         
00386         /* check for known and implemented algo's now (otherwise 
00387          * the function could return a wrong error
00388          */
00389         switch(sig_algo) {
00390                 case LDNS_RSAMD5:
00391                 case LDNS_RSASHA1:
00392                 case LDNS_DSA:
00393                         break;
00394                 case LDNS_DH:
00395                 case LDNS_ECC:
00396                 case LDNS_INDIRECT:
00397                         ldns_buffer_free(rawsig_buf);
00398                         ldns_buffer_free(verify_buf);
00399                         return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
00400                 default:
00401                         ldns_buffer_free(rawsig_buf);
00402                         ldns_buffer_free(verify_buf);
00403                         return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
00404         }
00405         
00406         result = LDNS_STATUS_ERR;
00407 
00408         /* create a buffer with b64 signature rdata */
00409         if (ldns_rdf2buffer_wire(rawsig_buf,
00410                                 ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) {
00411                 ldns_buffer_free(rawsig_buf);
00412                 ldns_buffer_free(verify_buf);
00413                 return LDNS_STATUS_MEM_ERR;
00414         }
00415 
00416         /* remove labels if the label count is higher than the label count
00417            from the rrsig */
00418         label_count = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 2));
00419 
00420         orig_ttl = ldns_rdf2native_int32(
00421                         ldns_rr_rdf(rrsig, 3));
00422 
00423         /* reset the ttl in the rrset with the orig_ttl from the sig */
00424         for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
00425                 if (label_count < 
00426                         ldns_dname_label_count(
00427                                 ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) {
00428                         (void) ldns_str2rdf_dname(&wildcard_name, "*");
00429                         wildcard_chopped = ldns_rdf_clone(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)));
00430                         while (label_count < ldns_dname_label_count(wildcard_chopped)) {
00431                                 wildcard_chopped_tmp = ldns_dname_left_chop(wildcard_chopped);
00432                                 ldns_rdf_deep_free(wildcard_chopped);
00433                                 wildcard_chopped = wildcard_chopped_tmp;
00434                         }
00435                         (void) ldns_dname_cat(wildcard_name, wildcard_chopped);
00436                         ldns_rdf_deep_free(wildcard_chopped);
00437                         ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)));
00438                         ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), 
00439                                         wildcard_name);
00440                                         
00441                 }
00442                 ldns_rr_set_ttl(
00443                                 ldns_rr_list_rr(rrset_clone, i),
00444                                 orig_ttl);
00445                 /* convert to lowercase */
00446                 ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
00447         }
00448 
00449         /* sort the rrset in canonical order  */
00450         ldns_rr_list_sort(rrset_clone);
00451 
00452         /* put the signature rr (without the b64) to the verify_buf */
00453         if (ldns_rrsig2buffer_wire(verify_buf, rrsig) != LDNS_STATUS_OK) {
00454                 ldns_rr_list_deep_free(rrset_clone);
00455                 ldns_buffer_free(rawsig_buf);
00456                 ldns_buffer_free(verify_buf);
00457                 return LDNS_STATUS_ERR;
00458         }
00459 
00460         /* add the rrset in verify_buf */
00461         if (ldns_rr_list2buffer_wire(verify_buf, rrset_clone) != LDNS_STATUS_OK) {
00462                 ldns_rr_list_deep_free(rrset_clone);
00463                 ldns_buffer_free(rawsig_buf);
00464                 ldns_buffer_free(verify_buf);
00465                 return LDNS_STATUS_ERR;
00466         }
00467 
00468         if (ldns_calc_keytag(key)
00469             ==
00470             ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig))
00471            ) {
00472                 key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00473                 
00474                 /* before anything, check if the keytags match */
00475 
00476                 /* put the key-data in a buffer, that's the third rdf, with
00477                  * the base64 encoded key data */
00478                 if (ldns_rdf2buffer_wire(key_buf,
00479                                 ldns_rr_rdf(key, 3)) != LDNS_STATUS_OK) {
00480                         ldns_rr_list_deep_free(rrset_clone);
00481                         ldns_buffer_free(rawsig_buf);
00482                         ldns_buffer_free(verify_buf);
00483                         /* returning is bad might screw up
00484                            good keys later in the list
00485                            what to do? */
00486                         return LDNS_STATUS_ERR;
00487                 }
00488                 
00489                 if (sig_algo == ldns_rdf2native_int8(ldns_rr_rdf(key, 2))) {
00490                         result = ldns_verify_rrsig_buffers(rawsig_buf, verify_buf, key_buf, sig_algo);
00491                 }
00492                 
00493                 ldns_buffer_free(key_buf); 
00494         }
00495          else {
00496                 /* No keys with the corresponding keytag are found */
00497                 result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
00498         }
00499         /* no longer needed */
00500         ldns_rr_list_deep_free(rrset_clone);
00501         ldns_buffer_free(rawsig_buf);
00502         ldns_buffer_free(verify_buf);
00503         return result;
00504 }
00505 
00506 ldns_status
00507 ldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
00508 {
00509         DSA *dsakey;
00510         DSA_SIG *dsasig;
00511         BIGNUM *R;
00512         BIGNUM *S;
00513         uint8_t t;
00514         int result;
00515 
00516         unsigned char *sha1_hash;
00517 
00518         dsakey = ldns_key_buf2dsa(key);
00519         if (!dsakey) {
00520                 return LDNS_STATUS_ERR;
00521         }
00522 
00523         /* extract the R and S field from the sig buffer */
00524         t = *(ldns_buffer_at(sig, 0));
00525         R = BN_new();
00526         (void) BN_bin2bn((unsigned char*)ldns_buffer_at(sig, 1), SHA_DIGEST_LENGTH, R);
00527         S = BN_new();
00528         (void) BN_bin2bn((unsigned char*)ldns_buffer_at(sig, 21), SHA_DIGEST_LENGTH, S);
00529 
00530         dsasig = DSA_SIG_new();
00531         if (!dsasig) {
00532                 return LDNS_STATUS_MEM_ERR;
00533         }
00534 
00535         dsasig->r = R;
00536         dsasig->s = S;
00537         sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(rrset), ldns_buffer_position(rrset), NULL);
00538         if (!sha1_hash) {
00539                 return LDNS_STATUS_ERR;
00540         }
00541 
00542         result = DSA_do_verify(sha1_hash, SHA_DIGEST_LENGTH, dsasig, dsakey);
00543 
00544         if (result == 1) {
00545                 return LDNS_STATUS_OK;
00546         } else {
00547                 return LDNS_STATUS_CRYPTO_BOGUS;
00548         }
00549 }
00550 
00551 ldns_status
00552 ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
00553 {
00554         RSA *rsakey;
00555         unsigned char *sha1_hash;
00556         ldns_status result;
00557 
00558         rsakey = ldns_key_buf2rsa(key);
00559         if (!rsakey) {
00560                 result = LDNS_STATUS_ERR;
00561         } else {
00562                 sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(rrset), ldns_buffer_position(rrset), NULL);
00563                 if (!sha1_hash) {
00564                         return LDNS_STATUS_ERR;
00565                 }
00566                 if (RSA_verify(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH, 
00567                                         (unsigned char*)ldns_buffer_begin(sig),
00568                                 (unsigned int)ldns_buffer_position(sig), rsakey) == 1) {
00569                         result = LDNS_STATUS_OK;
00570                 } else {
00571                         result = LDNS_STATUS_CRYPTO_BOGUS;
00572                 }
00573         }
00574 
00575         RSA_free(rsakey);
00576 
00577         return result;
00578 }
00579 
00580 
00581 ldns_status
00582 ldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
00583 {
00584         RSA *rsakey;
00585         unsigned char *md5_hash;
00586 
00587         rsakey = ldns_key_buf2rsa(key);
00588         if (!rsakey) {
00589                 return LDNS_STATUS_ERR;
00590         }
00591         md5_hash = MD5((unsigned char*)ldns_buffer_begin(rrset), 
00592                         (unsigned int)ldns_buffer_position(rrset), NULL);
00593         if (!md5_hash) {
00594                 return LDNS_STATUS_ERR;
00595         }
00596         if (RSA_verify(NID_md5, md5_hash, MD5_DIGEST_LENGTH, 
00597                                 (unsigned char*)ldns_buffer_begin(sig),
00598                         (unsigned int)ldns_buffer_position(sig), rsakey) == 1) {
00599                 return LDNS_STATUS_OK;
00600         } else {
00601                 return LDNS_STATUS_CRYPTO_BOGUS;
00602         }
00603         return true;
00604 }
00605 
00606 #ifdef HAVE_SSL
00607 DSA *
00608 ldns_key_buf2dsa(ldns_buffer *key)
00609 {
00610         uint8_t T;
00611         uint16_t length;
00612         uint16_t offset;
00613         DSA *dsa;
00614         BIGNUM *Q; BIGNUM *P;
00615         BIGNUM *G; BIGNUM *Y;
00616 
00617         T = *ldns_buffer_at(key, 0);
00618         length = (64 + T * 8);
00619         offset = 1;
00620         
00621         if (T > 8) {
00622                 return NULL;
00623         }
00624         
00625         Q = BN_bin2bn((unsigned char*)ldns_buffer_at(key, offset), SHA_DIGEST_LENGTH, NULL);
00626         offset += SHA_DIGEST_LENGTH;
00627         
00628         P = BN_bin2bn((unsigned char*)ldns_buffer_at(key, offset), (int)length, NULL);
00629         offset += length;
00630         
00631         G = BN_bin2bn((unsigned char*)ldns_buffer_at(key, offset), (int)length, NULL);
00632         offset += length;
00633         
00634         Y = BN_bin2bn((unsigned char*)ldns_buffer_at(key, offset), (int)length, NULL);
00635         offset += length;
00636         
00637         /* create the key and set its properties */
00638         dsa = DSA_new();
00639         dsa->p = P;
00640         dsa->q = Q;
00641         dsa->g = G;
00642         dsa->pub_key = Y;
00643 
00644         return dsa;
00645 }
00646 #endif
00647 
00648 RSA *
00649 ldns_key_buf2rsa(ldns_buffer *key)
00650 {
00651         uint16_t offset;
00652         uint16_t exp;
00653         uint16_t int16;
00654         RSA *rsa;
00655         BIGNUM *modulus;
00656         BIGNUM *exponent;
00657 
00658         if ((*ldns_buffer_at(key, 0)) == 0) {
00659                 /* need some smart comment here XXX*/
00660                 /* the exponent is too large so it's places
00661                  * futher...???? */
00662                 memcpy(&int16, ldns_buffer_at(key, 1), 2);
00663                 exp = ntohs(int16);
00664                 offset = 3;
00665         } else {
00666                 exp = *ldns_buffer_at(key, 0);
00667                 offset = 1;
00668         }
00669         
00670         /* Exponent */
00671         exponent = BN_new();
00672         (void) BN_bin2bn(
00673                          (unsigned char*)ldns_buffer_at(key, offset), (int)exp, exponent);
00674         offset += exp;
00675 
00676         /* Modulus */
00677         modulus = BN_new();
00678         /* capicity of the buffer must match the key length! */
00679         (void) BN_bin2bn((unsigned char*)ldns_buffer_at(key, offset), 
00680                          (int)(ldns_buffer_position(key) - offset), modulus);
00681 
00682         rsa = RSA_new();
00683         rsa->n = modulus;
00684         rsa->e = exponent;
00685 
00686         return rsa;
00687 }
00688 
00689 ldns_rr *
00690 ldns_key_rr2ds(const ldns_rr *key, ldns_hash h)
00691 {
00692         ldns_rdf *tmp;
00693         ldns_rr *ds;
00694         uint16_t keytag;
00695         uint8_t  sha1hash;
00696         uint8_t *digest;
00697         ldns_buffer *data_buf;
00698 
00699         if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY) {
00700                 return NULL;
00701         }
00702 
00703         ds = ldns_rr_new();
00704         if (!ds) {
00705                 return NULL;
00706         }
00707         ldns_rr_set_type(ds, LDNS_RR_TYPE_DS);
00708         ldns_rr_set_owner(ds, ldns_rdf_clone(
00709                                 ldns_rr_owner(key)));
00710         ldns_rr_set_ttl(ds, ldns_rr_ttl(key));
00711         ldns_rr_set_class(ds, ldns_rr_get_class(key));
00712 
00713         switch(h) {
00714                 default:
00715                 case LDNS_SHA1:
00716                         digest = LDNS_XMALLOC(uint8_t, SHA_DIGEST_LENGTH);
00717                         if (!digest) {
00718                                 ldns_rr_free(ds);
00719                                 return NULL;
00720                         }
00721                 break;
00722                 case LDNS_SHA256:
00723 #ifdef SHA256_DIGEST_LENGTH
00724                         digest = LDNS_XMALLOC(uint8_t, SHA256_DIGEST_LENGTH);
00725                         if (!digest) {
00726                                 ldns_rr_free(ds);
00727                                 return NULL;
00728                         }
00729 #else
00730                         ldns_rr_free(ds);
00731                         return NULL;
00732 #endif
00733                 break;
00734         }
00735 
00736         data_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00737         if (!data_buf) {
00738                 LDNS_FREE(digest);
00739                 ldns_rr_free(ds);
00740                 return NULL;
00741         }
00742 
00743         /* keytag */
00744         keytag = htons(ldns_calc_keytag((ldns_rr*)key));
00745         tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16, sizeof(uint16_t), &keytag);
00746         ldns_rr_push_rdf(ds, tmp);
00747 
00748         /* copy the algorithm field */
00749         ldns_rr_push_rdf(ds, ldns_rdf_clone( ldns_rr_rdf(key, 2))); /* second rfd */
00750 
00751         /* digest hash type */
00752         sha1hash = (uint8_t)h;
00753         tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, sizeof(uint8_t), &sha1hash);
00754         ldns_rr_push_rdf(ds, tmp);
00755 
00756         /* digest */
00757         /* owner name */
00758         tmp = ldns_rdf_clone(ldns_rr_owner(key));
00759         ldns_dname2canonical(tmp);
00760         if (ldns_rdf2buffer_wire(data_buf, tmp) != LDNS_STATUS_OK) {
00761                 LDNS_FREE(digest);
00762                 ldns_buffer_free(data_buf);
00763                 ldns_rr_free(ds);
00764                 ldns_rdf_deep_free(tmp);
00765                 return NULL;
00766         }
00767         ldns_rdf_deep_free(tmp);
00768 
00769         /* all the rdata's */
00770         if (ldns_rr_rdata2buffer_wire(data_buf, (ldns_rr*)key) != LDNS_STATUS_OK) { 
00771                 LDNS_FREE(digest);
00772                 ldns_buffer_free(data_buf);
00773                 ldns_rr_free(ds);
00774                 return NULL;
00775         }
00776         switch(h) {
00777                 case LDNS_SHA1:
00778                 (void) SHA1((unsigned char *) ldns_buffer_begin(data_buf),
00779                             ldns_buffer_position(data_buf),
00780                             (unsigned char*) digest);
00781 
00782                 tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, SHA_DIGEST_LENGTH,
00783                                 digest);
00784                 ldns_rr_push_rdf(ds, tmp);
00785 
00786                 break;
00787                 case LDNS_SHA256:
00788 #ifdef SHA256_DIGEST_LENGTH
00789                 (void) SHA256((unsigned char *) ldns_buffer_begin(data_buf),
00790                             ldns_buffer_position(data_buf),
00791                             (unsigned char*) digest);
00792                 tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, SHA256_DIGEST_LENGTH,
00793                                 digest);
00794                 ldns_rr_push_rdf(ds, tmp);
00795 #endif
00796                 break;
00797         }
00798 
00799         LDNS_FREE(digest);
00800         ldns_buffer_free(data_buf);
00801         return ds;
00802 }
00803 
00804 /*
00805  * use this function to sign with a public/private key alg
00806  * return the created signatures
00807  */
00808 ldns_rr_list *
00809 ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
00810 {
00811         ldns_rr_list *signatures;
00812         ldns_rr_list *rrset_clone;
00813         ldns_rr *current_sig;
00814         ldns_rdf *b64rdf;
00815         ldns_key *current_key;
00816         size_t key_count;
00817         uint16_t i;
00818         ldns_buffer *sign_buf;
00819         uint32_t orig_ttl;
00820         time_t now;
00821         uint8_t label_count;
00822         ldns_rdf *first_label;
00823         ldns_rdf *wildcard_label;
00824         ldns_rdf *new_owner;
00825 
00826         if (!rrset || ldns_rr_list_rr_count(rrset) < 1 || !keys) {
00827                 return NULL;
00828         }
00829 
00830         key_count = 0;
00831         signatures = ldns_rr_list_new();
00832 
00833         /* prepare a signature and add all the know data
00834          * prepare the rrset. Sign this together.  */
00835         rrset_clone = ldns_rr_list_clone(rrset);
00836         if (!rrset_clone) {
00837                 return NULL;
00838         }
00839 
00840         /* check for label count and wildcard */
00841         label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset, 0)));
00842         (void) ldns_str2rdf_dname(&wildcard_label, "*");
00843         first_label = ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(rrset, 0)), 0);
00844         if (ldns_rdf_compare(first_label, wildcard_label) == 0) {
00845                 label_count--;
00846                 for (i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
00847                         new_owner = ldns_dname_cat_clone(wildcard_label, 
00848                                         ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i))));
00849                         ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), new_owner);
00850                 }
00851         }
00852         ldns_rdf_deep_free(wildcard_label);
00853         ldns_rdf_deep_free(first_label);
00854 
00855         /* make it canonical */
00856         for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
00857                 ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
00858         }
00859         /* sort */
00860         ldns_rr_list_sort(rrset_clone);
00861         
00862         for (key_count = 0; key_count < ldns_key_list_key_count(keys); key_count++) {
00863                 sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00864                 b64rdf = NULL;
00865 
00866                 current_key = ldns_key_list_key(keys, key_count);
00867                 /* sign all RRs with keys that have ZSKbit, !SEPbit.
00868                    sign DNSKEY RRs with keys that have ZSKbit&SEPbit */
00869                 if (
00870                         ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY &&
00871                         (!(ldns_key_flags(current_key) & LDNS_KEY_SEP_KEY) ||
00872                         ldns_rr_get_type(ldns_rr_list_rr(rrset, 0)) == LDNS_RR_TYPE_DNSKEY)
00873                    ) {
00874                         current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
00875                         
00876                         /* set the type on the new signature */
00877                         orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));
00878 
00879                         ldns_rr_set_ttl(current_sig, orig_ttl);
00880                         ldns_rr_set_owner(current_sig, 
00881                                         ldns_rdf_clone(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, 0))));
00882 
00883                         /* fill in what we know of the signature */
00884 
00885                         /* set the orig_ttl */
00886                         (void)ldns_rr_rrsig_set_origttl(current_sig, 
00887                                         ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, orig_ttl));
00888                         /* the signers name */
00889 
00890                         (void)ldns_rr_rrsig_set_signame(current_sig, 
00891                                         ldns_rdf_clone(ldns_key_pubkey_owner(current_key)));
00892                         /* label count - get it from the first rr in the rr_list */
00893                         (void)ldns_rr_rrsig_set_labels(current_sig, 
00894                                         ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, label_count));
00895                         /* inception, expiration */
00896                         now = time(NULL);
00897                         if (ldns_key_inception(current_key) != 0) {
00898                                 (void)ldns_rr_rrsig_set_inception(current_sig,
00899                                                 ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, 
00900                                                         ldns_key_inception(current_key)));
00901                         } else {
00902                                 (void)ldns_rr_rrsig_set_inception(current_sig,
00903                                                 ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
00904                         }
00905                         if (ldns_key_expiration(current_key) != 0) {
00906                                 (void)ldns_rr_rrsig_set_expiration(current_sig,
00907                                                 ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, 
00908                                                         ldns_key_expiration(current_key)));
00909                         } else {
00910                                 (void)ldns_rr_rrsig_set_expiration(current_sig,
00911                                                 ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, 
00912                                                         now + LDNS_DEFAULT_EXP_TIME));
00913                         }
00914 
00915                         /* key-tag */
00916 /*printf("SETTING KEYTAG TO: %u\n", ldns_key_keytag(current_key));*/
00917                         (void)ldns_rr_rrsig_set_keytag(current_sig,
00918                                         ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 
00919                                                 ldns_key_keytag(current_key)));
00920 
00921                         /* algorithm - check the key and substitute that */
00922                         (void)ldns_rr_rrsig_set_algorithm(current_sig,
00923                                         ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, 
00924                                                 ldns_key_algorithm(current_key)));
00925                         /* type-covered */
00926                         (void)ldns_rr_rrsig_set_typecovered(current_sig,
00927                                         ldns_native2rdf_int16(LDNS_RDF_TYPE_TYPE,
00928                                                 ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0))));
00929                         /* right now, we have: a key, a semi-sig and an rrset. For
00930                          * which we can create the sig and base64 encode that and
00931                          * add that to the signature */
00932                         
00933                         if (ldns_rrsig2buffer_wire(sign_buf, current_sig) != LDNS_STATUS_OK) {
00934                                 ldns_buffer_free(sign_buf);
00935                                 /* ERROR */
00936                                 ldns_rr_list_deep_free(rrset_clone);
00937                                 return NULL;
00938                         }
00939                         /* add the rrset in sign_buf */
00940 
00941                         if (ldns_rr_list2buffer_wire(sign_buf, rrset_clone) != LDNS_STATUS_OK) {
00942                                 ldns_buffer_free(sign_buf);
00943                                 ldns_rr_list_deep_free(rrset_clone);
00944                                 return NULL;
00945                         }
00946                         
00947                         switch(ldns_key_algorithm(current_key)) {
00948                                 case LDNS_SIGN_DSA:
00949                                         b64rdf = ldns_sign_public_dsa(sign_buf, ldns_key_dsa_key(current_key));
00950                                         break;
00951                                 case LDNS_SIGN_RSASHA1:
00952                                         b64rdf = ldns_sign_public_rsasha1(sign_buf, ldns_key_rsa_key(current_key));
00953                                         break;
00954                                 case LDNS_SIGN_RSAMD5:
00955                                         b64rdf = ldns_sign_public_rsamd5(sign_buf, ldns_key_rsa_key(current_key));
00956                                         break;
00957                                 default:
00958                                         /* do _you_ know this alg? */
00959                                         break;
00960                         }
00961                         if (!b64rdf) {
00962                                 /* signing went wrong */
00963                                 ldns_rr_list_deep_free(rrset_clone);
00964                                 return NULL;
00965                         }
00966                         ldns_rr_rrsig_set_sig(current_sig, b64rdf);
00967 
00968                         /* push the signature to the signatures list */
00969                         ldns_rr_list_push_rr(signatures, current_sig);
00970                 }
00971                 ldns_buffer_free(sign_buf); /* restart for the next key */
00972         }
00973         ldns_rr_list_deep_free(rrset_clone);
00974 
00975         return signatures;
00976 }
00977 
00978 ldns_rdf *
00979 ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
00980 {
00981         unsigned char *sha1_hash;
00982         ldns_rdf *sigdata_rdf;
00983         ldns_buffer *b64sig;
00984 
00985         DSA_SIG *sig;
00986         uint8_t *data;
00987         size_t pad;
00988 
00989         b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00990         if (!b64sig) {
00991                 return NULL;
00992         }
00993         
00994         sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
00995                         ldns_buffer_position(to_sign), NULL);
00996         if (!sha1_hash) {
00997                 ldns_buffer_free(b64sig);
00998                 return NULL;
00999         }
01000 
01001 
01002         sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key);
01003 
01004         data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH);
01005 
01006         data[0] = 1;
01007         pad = 20 - (size_t) BN_num_bytes(sig->r);
01008         if (pad > 0) {
01009                 memset(data + 1, 0, pad);
01010         }
01011         BN_bn2bin(sig->r, (unsigned char *) (data + 1) + pad);
01012 
01013         pad = 20 - (size_t) BN_num_bytes(sig->s);
01014         if (pad > 0) {
01015                 memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad);
01016         }
01017         BN_bn2bin(sig->s, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad));
01018 
01019         sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,  1 + 2 * SHA_DIGEST_LENGTH, data);
01020 
01021         ldns_buffer_free(b64sig);
01022         LDNS_FREE(data);
01023 
01024         return sigdata_rdf;
01025 }
01026 
01027 ldns_rdf *
01028 ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key)
01029 {
01030         unsigned char *sha1_hash;
01031         unsigned int siglen;
01032         ldns_rdf *sigdata_rdf;
01033         ldns_buffer *b64sig;
01034         int result;
01035 
01036         siglen = 0;
01037         b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
01038         if (!b64sig) {
01039                 return NULL;
01040         }
01041 
01042         sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
01043                         ldns_buffer_position(to_sign), NULL);
01044         if (!sha1_hash) {
01045                 ldns_buffer_free(b64sig);
01046                 return NULL;
01047         }
01048 
01049         result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH,
01050                         (unsigned char*)ldns_buffer_begin(b64sig),
01051                         &siglen, key);
01052         if (result != 1) {
01053                 return NULL;
01054         }
01055 
01056         sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 
01057                         ldns_buffer_begin(b64sig));
01058         ldns_buffer_free(b64sig); /* can't free this buffer ?? */
01059         return sigdata_rdf;
01060 }
01061 
01062 ldns_rdf *
01063 ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key)
01064 {
01065         unsigned char *md5_hash;
01066         unsigned int siglen;
01067         ldns_rdf *sigdata_rdf;
01068         ldns_buffer *b64sig;
01069 
01070         b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
01071         if (!b64sig) {
01072                 return NULL;
01073         }
01074         
01075         md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign),
01076                         ldns_buffer_position(to_sign), NULL);
01077         if (!md5_hash) {
01078                 ldns_buffer_free(b64sig);
01079                 return NULL;
01080         }
01081 
01082         RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH,
01083                         (unsigned char*)ldns_buffer_begin(b64sig),
01084                         &siglen, key);
01085 
01086         sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 
01087                         ldns_buffer_begin(b64sig));
01088         ldns_buffer_free(b64sig);
01089         return sigdata_rdf;
01090 }
01091 
01092 ldns_rr *
01093 ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs)
01094 {
01095         /* we do not do any check here - garbage in, garbage out */
01096         
01097         /* the the start and end names - get the type from the
01098          * before rrlist */
01099 
01100         /* we don't have an nsec encoder... :( */
01101 
01102         /* inefficient, just give it a name, a next name, and a list of rrs */
01103         /* we make 1 big uberbitmap first, then windows */
01104         /* todo: make something more efficient :) */
01105         uint16_t i;
01106         ldns_rr *i_rr;
01107 
01108         uint8_t *bitmap = LDNS_XMALLOC(uint8_t, 2);
01109         uint16_t bm_len = 0;
01110         uint16_t i_type;
01111 
01112         ldns_rr *nsec = NULL;
01113 
01114         uint8_t *data = NULL;
01115         uint8_t cur_data[32];
01116         uint8_t cur_window = 0;
01117         uint8_t cur_window_max = 0;
01118         uint16_t cur_data_size = 0;
01119 
01120         nsec = ldns_rr_new();
01121         ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC);
01122         ldns_rr_set_owner(nsec, ldns_rdf_clone(cur_owner));
01123         /* TODO: TTL jelte? */
01124         ldns_rr_push_rdf(nsec, ldns_rdf_clone(next_owner));
01125 
01126         bitmap[0] = 0;
01127         for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
01128                 i_rr = ldns_rr_list_rr(rrs, i);
01129 
01130                 if (ldns_rdf_compare(cur_owner,
01131                                      ldns_rr_owner(i_rr)) == 0) {
01132                         /* add type to bitmap */
01133                         i_type = ldns_rr_get_type(i_rr);
01134                         if ((i_type / 8) + 1 > bm_len) {
01135                                 bitmap = LDNS_XREALLOC(bitmap, uint8_t, (i_type / 8) + 2);
01136                                 /* set to 0 */
01137                                 for (; bm_len <= i_type / 8; bm_len++) {
01138                                         bitmap[bm_len] = 0;
01139                                 }
01140                         }
01141                         ldns_set_bit(bitmap + (int) i_type / 8, (int) (7 - (i_type % 8)), true);
01142                 }
01143         }
01144         /* add NSEC and RRSIG anyway */
01145         i_type = LDNS_RR_TYPE_RRSIG;
01146         if (i_type / 8 > bm_len) {
01147                 bitmap = LDNS_XREALLOC(bitmap, uint8_t, (i_type / 8) + 2);
01148                 /* set to 0 */
01149                 for (; bm_len <= i_type / 8; bm_len++) {
01150                         bitmap[bm_len] = 0;
01151                 }
01152         }
01153         ldns_set_bit(bitmap + (int) i_type / 8, (int) (7 - (i_type % 8)), true);
01154         i_type = LDNS_RR_TYPE_NSEC;
01155 
01156         if (i_type / 8 > bm_len) {
01157                 bitmap = LDNS_XREALLOC(bitmap, uint8_t, (i_type / 8) + 2);
01158                 /* set to 0 */
01159                 for (; bm_len <= i_type / 8; bm_len++) {
01160                         bitmap[bm_len] = 0;
01161                 }
01162         }
01163         ldns_set_bit(bitmap + (int) i_type / 8, (int) (7 - (i_type % 8)), true);
01164 
01165         memset(cur_data, 0, 32);
01166         for (i = 0; i < bm_len; i++) {
01167                 if (i / 32 > cur_window) {
01168                         /* check, copy, new */
01169                         if (cur_window_max > 0) {
01170                                 /* this window has stuff, add it */
01171                                 data = LDNS_XREALLOC(data, uint8_t, cur_data_size + cur_window_max + 3);
01172                                 data[cur_data_size] = cur_window;
01173                                 data[cur_data_size + 1] = cur_window_max + 1;
01174                                 memcpy(data + cur_data_size + 2, cur_data, cur_window_max+1);
01175                                 cur_data_size += cur_window_max + 3;
01176                         }
01177                         cur_window++;
01178                         cur_window_max = 0;
01179                         memset(cur_data, 0, 32);
01180                 } else {
01181                         cur_data[i%32] = bitmap[i];
01182                         if (bitmap[i] > 0) {
01183                                 cur_window_max = i%32;
01184                         }
01185                 }
01186         }
01187         if (cur_window_max > 0) {
01188                 /* this window has stuff, add it */
01189                 data = LDNS_XREALLOC(data, uint8_t, cur_data_size + cur_window_max + 3);
01190                 data[cur_data_size] = cur_window;
01191                 data[cur_data_size + 1] = cur_window_max + 1;
01192                 memcpy(data + cur_data_size + 2, cur_data, cur_window_max+1);
01193                 cur_data_size += cur_window_max + 3;
01194         }
01195 
01196         ldns_rr_push_rdf(nsec, ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC, cur_data_size, data));
01197 
01198         LDNS_FREE(bitmap);
01199         LDNS_FREE(data);
01200         return nsec;
01201 }
01202 
01203 bool
01204 ldns_nsec_bitmap_covers_type(const ldns_rdf *nsec_bitmap, ldns_rr_type type)
01205 {
01206         uint8_t *bitmap;
01207         uint16_t i;
01208         uint8_t window_block_nr;
01209         
01210         if (!nsec_bitmap) {
01211                 return false;
01212         }
01213 
01214         /* Check the bitmap if our type is there */
01215         bitmap = ldns_rdf_data(nsec_bitmap);
01216         window_block_nr = (uint8_t) (type / 256);
01217         i = 0;
01218 
01219         while (i < ldns_rdf_size(nsec_bitmap)) {
01220                 if (bitmap[i] == window_block_nr) {
01221                         /* this is the right window, check the bit */
01222                         if ((uint8_t) (type / 8) < bitmap[i + 1] &&
01223                             ldns_get_bit(&bitmap[i + 1 + (type / 8)], (size_t) (7 - (type % 8)))) {
01224                                 return true;
01225                         } else {
01226                                 return false;
01227                         }
01228                 } else {
01229                         /* this is the wrong window, go to the next */
01230                         i++;
01231                         i += bitmap[i];
01232                 }
01233         }
01234 
01235         return false;
01236 }
01237 
01238 bool
01239 ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name)
01240 {
01241         ldns_rdf *nsec_owner = ldns_rr_owner(nsec);
01242         ldns_rdf *nsec_next = ldns_rr_rdf(nsec, 0);
01243         
01244         /* in the case of the last nsec */
01245         if(ldns_dname_compare(nsec_owner, nsec_next) > 0)
01246                 return (ldns_dname_compare(nsec_owner, name) <= 0 ||
01247                         ldns_dname_compare(name, nsec_next) < 0);
01248 
01249         return (ldns_dname_compare(nsec_owner, name) <= 0 &&
01250             ldns_dname_compare(name, nsec_next) < 0);
01251 }
01252 
01253 /* sig may be null - if so look in the packet */
01254 ldns_status
01255 ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, 
01256                 ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys)
01257 {
01258         ldns_rr_list *rrset;
01259         ldns_rr_list *sigs;
01260         ldns_rr_list *sigs_covered;
01261         ldns_rdf *rdf_t;
01262         ldns_rr_type t_netorder;
01263 
01264         if (!k) {
01265                 return LDNS_STATUS_ERR;
01266                 /* return LDNS_STATUS_CRYPTO_NO_DNSKEY; */
01267         }
01268 
01269         if (t == LDNS_RR_TYPE_RRSIG) {
01270                 /* we don't have RRSIG(RRSIG) (yet? ;-) ) */
01271                 /* return LDNS_STATUS_ERR; */
01272                 return LDNS_STATUS_ERR;
01273         }
01274         
01275         if (s) {
01276                 /* if s is not NULL, the sigs are given to use */
01277                 sigs = s;
01278         } else {
01279                 /* otherwise get them from the packet */
01280                 sigs = ldns_pkt_rr_list_by_name_and_type(p, o, LDNS_RR_TYPE_RRSIG, 
01281                                 LDNS_SECTION_ANY_NOQUESTION);
01282                 if (!sigs) {
01283                         /* no sigs */
01284                         return LDNS_STATUS_ERR;
01285                         /* return LDNS_STATUS_CRYPTO_NO_RRSIG; */
01286                 }
01287         }
01288 
01289         /* *sigh* rrsig are subtyped, so now we need to find the correct
01290          * sigs for the type t
01291          */
01292         t_netorder = htons(t); /* rdf are in network order! */
01293         rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, sizeof(ldns_rr_type), &t_netorder);
01294         sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0);
01295         
01296         rrset = ldns_pkt_rr_list_by_name_and_type(p, o, t, LDNS_SECTION_ANY_NOQUESTION);
01297 
01298         if (!rrset) {
01299                 return LDNS_STATUS_ERR;
01300         }
01301 
01302         if (!sigs_covered) {
01303                 return LDNS_STATUS_ERR;
01304         }
01305 
01306         return ldns_verify(rrset, sigs, k, good_keys);
01307 }
01308 
01309 ldns_zone *
01310 ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list)
01311 {
01312         /*
01313          * Algorithm to be created:
01314          * - sort the rrs (name/class/type?)
01315          * - if sorted, every next rr is belongs either to the rrset
01316          * you are working on, or the rrset is complete
01317          * for each rrset, calculate rrsig and nsec
01318          * put the rrset, rrsig and nsec in the new zone
01319          * done!
01320          * ow and don't sign old rrsigs etc.
01321          */
01322          
01323         ldns_zone *signed_zone;
01324         ldns_rr_list *cur_rrset;
01325         ldns_rr_list *cur_rrsigs;
01326         ldns_rr_list *orig_zone_rrs;
01327         ldns_rr_list *signed_zone_rrs;
01328         ldns_rr_list *pubkeys;
01329         ldns_rr_list *glue_rrs;
01330         
01331         ldns_rdf *start_dname = NULL;
01332         ldns_rdf *cur_dname = NULL;
01333         ldns_rr *next_rr = NULL;
01334         ldns_rdf *next_dname = NULL;
01335         ldns_rr *nsec;
01336         ldns_rr *ckey;
01337         uint16_t i;
01338         ldns_rr_type cur_rrset_type;
01339         
01340         signed_zone = ldns_zone_new();
01341 
01342         /* there should only be 1 SOA, so the soa record is 1 rrset */
01343         cur_rrsigs = NULL;
01344         ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone)));
01345         /*ldns_rr2canonical(ldns_zone_soa(signed_zone));*/
01346         
01347         orig_zone_rrs = ldns_rr_list_clone(ldns_zone_rrs(zone));
01348 
01349         ldns_rr_list_push_rr(orig_zone_rrs, ldns_rr_clone(ldns_zone_soa(zone)));
01350         
01351         /* canon now, needed for correct nsec creation */
01352         /*
01353         for (i = 0; i < ldns_rr_list_rr_count(orig_zone_rrs); i++) {
01354                 ldns_rr2canonical(ldns_rr_list_rr(orig_zone_rrs, i));
01355         }
01356         */
01357         glue_rrs = ldns_zone_glue_rr_list(zone);
01358 
01359         /* add the key (TODO: check if it's there already? */
01360         pubkeys = ldns_rr_list_new();
01361         for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
01362                 ckey = ldns_key2rr(ldns_key_list_key(key_list, i));
01363                 ldns_rr_list_push_rr(pubkeys, ckey);
01364         }
01365 
01366         signed_zone_rrs = ldns_rr_list_new();
01367         
01368         ldns_rr_list_sort(orig_zone_rrs);
01369         
01370         /* add nsecs */
01371         for (i = 0; i < ldns_rr_list_rr_count(orig_zone_rrs); i++) {
01372                 if (!start_dname) {
01373                         /*start_dname = ldns_rr_owner(ldns_zone_soa(zone));*/
01374                         start_dname = ldns_rr_owner(ldns_rr_list_rr(orig_zone_rrs, i));
01375                         cur_dname = start_dname;
01376                 } else {
01377                         next_rr = ldns_rr_list_rr(orig_zone_rrs, i);
01378                         next_dname = ldns_rr_owner(next_rr);
01379                         if (ldns_rdf_compare(cur_dname, next_dname) != 0) {
01380                                 /* skip glue */
01381                                 if (ldns_rr_list_contains_rr(glue_rrs, next_rr)) {
01382                                         cur_dname = next_dname;
01383                                 } else {
01384                                         nsec = ldns_create_nsec(cur_dname, 
01385                                                                 next_dname,
01386                                                                 orig_zone_rrs);
01387                                         ldns_rr_set_ttl(nsec, ldns_rdf2native_int32(ldns_rr_rdf(ldns_zone_soa(zone), 6)));
01388                                         ldns_rr_list_push_rr(signed_zone_rrs, nsec);
01389                                         /*start_dname = next_dname;*/
01390                                         cur_dname = next_dname;
01391                                 }
01392                         }
01393                 }
01394                 ldns_rr_list_push_rr(signed_zone_rrs, ldns_rr_list_rr(orig_zone_rrs, i));
01395         }
01396         nsec = ldns_create_nsec(cur_dname, 
01397                                 start_dname,
01398                                 orig_zone_rrs);
01399         ldns_rr_list_push_rr(signed_zone_rrs, nsec);
01400         ldns_rr_list_free(orig_zone_rrs);
01401         ldns_rr_set_ttl(nsec, ldns_rdf2native_int32(ldns_rr_rdf(ldns_zone_soa(zone), 6)));
01402 
01403         /* Sign all rrsets in the zone */
01404         cur_rrset = ldns_rr_list_pop_rrset(signed_zone_rrs);
01405         while (cur_rrset) {
01406                 /* don't sign certain types */
01407                 cur_rrset_type = ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0));
01408                 cur_dname = ldns_rr_owner(ldns_rr_list_rr(cur_rrset, 0));
01409 
01410                 /* if we have KSKs, use them for DNSKEYS, otherwise
01411                    make them selfsigned (?) */
01412                 /* don't sign sigs, delegations, and glue */
01413                 if (cur_rrset_type != LDNS_RR_TYPE_RRSIG &&
01414                     ((ldns_dname_is_subdomain(cur_dname, ldns_rr_owner(ldns_zone_soa(signed_zone)))
01415                       && cur_rrset_type != LDNS_RR_TYPE_NS
01416                      ) ||
01417                      ldns_rdf_compare(cur_dname, ldns_rr_owner(ldns_zone_soa(signed_zone))) == 0
01418                     ) &&
01419                     !(ldns_rr_list_contains_rr(glue_rrs, ldns_rr_list_rr(cur_rrset, 0)))
01420                    ) {
01421                         cur_rrsigs = ldns_sign_public(cur_rrset, key_list);
01422                         if (!cur_rrsigs) {
01423                                 ldns_zone_deep_free(signed_zone);
01424                                 ldns_rr_list_deep_free(signed_zone_rrs);
01425                                 ldns_rr_list_deep_free(pubkeys);
01426                                 ldns_rr_list_free(glue_rrs);
01427                                 return NULL;
01428                         }
01429                         /* TODO: make optional, replace exit call */
01430                         /* if not optional it should be left out completely
01431                            (for it is possible to generate bad signarures, by
01432                            specifying a future inception date */
01433                         
01434                         ldns_zone_push_rr_list(signed_zone, cur_rrset);
01435                         ldns_zone_push_rr_list(signed_zone, cur_rrsigs);
01436                         ldns_rr_list_free(cur_rrsigs);
01437                 } else {
01438                         /* push it unsigned (glue, sigs, delegations) */
01439                         ldns_zone_push_rr_list(signed_zone, cur_rrset);
01440                 }
01441                 ldns_rr_list_free(cur_rrset);
01442                 cur_rrset = ldns_rr_list_pop_rrset(signed_zone_rrs);
01443         }
01444         ldns_rr_list_deep_free(signed_zone_rrs);
01445         ldns_rr_list_deep_free(pubkeys);
01446         ldns_rr_list_free(glue_rrs);
01447         return signed_zone;
01448         
01449 }
01450 
01451 #endif /* HAVE_SSL */

Generated on Thu Nov 29 14:14:59 2007 for ldns by  doxygen 1.5.1