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

Generated on Wed Oct 10 16:24:48 2007 for ldns by  doxygen 1.5.2