int dst_s_conv_bignum_b64_to_u8(const char **buf, u_char *loc, const unsigned loclen) { unsigned blen; char *bp; u_char bstr[RAW_KEY_SIZE]; int res = 0; if (buf == NULL || *buf == NULL) { /* error checks */ EREPORT(("dst_s_conv_bignum_b64_to_u8: null input buffer.\n")); return (0); } bp = strchr(*buf, '\n'); /* find length of input line */ if (bp != NULL) *bp = '\0'; res = b64_pton(*buf, bstr, sizeof(bstr)); if (res <= 0) { EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is null.\n")); return (0); } blen = (unsigned) res; if (loclen < blen) { EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is longer than output buffer.\n")); return (0); } if (bp) *buf = bp; /* advancing buffer past \n */ memset(loc, 0, loclen - blen); /* clearing unused output area */ memcpy(loc + loclen - blen, bstr, blen); /* write last blen bytes */ return (blen); }
int dst_key_to_dnskey(const DST_KEY *key, u_char *out_storage, const int out_len) { u_int16_t val; int loc = 0; int enc_len = 0; if (key == NULL) return (-1); if (!dst_check_algorithm(key->dk_alg)) { /*%< make sure alg is available */ EREPORT(("dst_key_to_dnskey(): Algorithm %d not suppored\n", key->dk_alg)); return (UNSUPPORTED_KEYALG); } memset(out_storage, 0, out_len); val = (u_int16_t)(key->dk_flags & 0xffff); dst_s_put_int16(out_storage, val); loc += 2; out_storage[loc++] = (u_char) key->dk_proto; out_storage[loc++] = (u_char) key->dk_alg; if (key->dk_flags > 0xffff) { /*%< Extended flags */ val = (u_int16_t)((key->dk_flags >> 16) & 0xffff); dst_s_put_int16(&out_storage[loc], val); loc += 2; }
DST_KEY * dst_dnskey_to_key(const char *in_name, const u_char *rdata, const int len) { DST_KEY *key_st; int alg ; int start = DST_KEY_START; if (rdata == NULL || len <= DST_KEY_ALG) /*%< no data */ return (NULL); alg = (u_int8_t) rdata[DST_KEY_ALG]; if (!dst_check_algorithm(alg)) { /*%< make sure alg is available */ EREPORT(("dst_dnskey_to_key(): Algorithm %d not suppored\n", alg)); return (NULL); } if (in_name == NULL) return (NULL); if ((key_st = dst_s_get_key_struct(in_name, alg, 0, 0, 0)) == NULL) return (NULL); key_st->dk_id = dst_s_dns_key_id(rdata, len); key_st->dk_flags = dst_s_get_int16(rdata); key_st->dk_proto = (u_int16_t) rdata[DST_KEY_PROT]; if (key_st->dk_flags & DST_EXTEND_FLAG) { u_int32_t ext_flags; ext_flags = (u_int32_t) dst_s_get_int16(&rdata[DST_EXT_FLAG]); key_st->dk_flags = key_st->dk_flags | (ext_flags << 16); start += 2; } /* * now point to the begining of the data representing the encoding * of the key */ if (key_st->dk_func && key_st->dk_func->from_dns_key) { if (key_st->dk_func->from_dns_key(key_st, &rdata[start], len - start) > 0) return (key_st); } else EREPORT(("dst_dnskey_to_public_key(): unsuppored alg %d\n", alg)); SAFE_FREE(key_st); return (key_st); }
static int dst_s_write_private_key(const DST_KEY *key) { u_char encoded_block[RAW_KEY_SIZE]; char file[PATH_MAX]; int len; FILE *fp; /* First encode the key into the portable key format */ if (key == NULL) return (-1); if (key->dk_KEY_struct == NULL) return (0); /*%< null key has no private key */ if (key->dk_func == NULL || key->dk_func->to_file_fmt == NULL) { EREPORT(("dst_write_private_key(): Unsupported operation %d\n", key->dk_alg)); return (-5); } else if ((len = key->dk_func->to_file_fmt(key, (char *)encoded_block, sizeof(encoded_block))) <= 0) { EREPORT(("dst_write_private_key(): Failed encoding private RSA bsafe key %d\n", len)); return (-8); } /* Now I can create the file I want to use */ dst_s_build_filename(file, key->dk_key_name, key->dk_id, key->dk_alg, PRIVATE_KEY, PATH_MAX); /* Do not overwrite an existing file */ if ((fp = dst_s_fopen(file, "w", 0600)) != NULL) { int nn; if ((nn = fwrite(encoded_block, 1, len, fp)) != len) { EREPORT(("dst_write_private_key(): Write failure on %s %d != %d errno=%d\n", file, len, nn, errno)); fclose(fp); return (-5); } fclose(fp); } else { EREPORT(("dst_write_private_key(): Can not create file %s\n" ,file)); return (-6); } memset(encoded_block, 0, len); return (len); }
static int dst_s_write_public_key(const DST_KEY *key) { FILE *fp; char filename[PATH_MAX]; u_char out_key[RAW_KEY_SIZE]; char enc_key[RAW_KEY_SIZE]; int len = 0; int mode; memset(out_key, 0, sizeof(out_key)); if (key == NULL) { EREPORT(("dst_write_public_key(): No key specified \n")); return (0); } else if ((len = dst_key_to_dnskey(key, out_key, sizeof(out_key)))< 0) return (0); /* Make the filename */ if (dst_s_build_filename(filename, key->dk_key_name, key->dk_id, key->dk_alg, PUBLIC_KEY, PATH_MAX) == -1) { EREPORT(("dst_write_public_key(): Cannot make filename from %s, %d, and %s\n", key->dk_key_name, key->dk_id, PUBLIC_KEY)); return (0); } /* XXX in general this should be a check for symmetric keys */ mode = (key->dk_alg == KEY_HMAC_MD5) ? 0600 : 0644; /* create public key file */ if ((fp = dst_s_fopen(filename, "w+", mode)) == NULL) { EREPORT(("DST_write_public_key: open of file:%s failed (errno=%d)\n", filename, errno)); return (0); } /*write out key first base64 the key data */ if (key->dk_flags & DST_EXTEND_FLAG) b64_ntop(&out_key[6], len - 6, enc_key, sizeof(enc_key)); else b64_ntop(&out_key[4], len - 4, enc_key, sizeof(enc_key)); fprintf(fp, "%s IN KEY %d %d %d %s\n", key->dk_key_name, key->dk_flags, key->dk_proto, key->dk_alg, enc_key); fclose(fp); return (1); }
DST_KEY * dst_read_key(const char *in_keyname, const u_int16_t in_id, const int in_alg, const int type) { char keyname[PATH_MAX]; DST_KEY *dg_key = NULL, *pubkey = NULL; if (!dst_check_algorithm(in_alg)) { /*%< make sure alg is available */ EREPORT(("dst_read_private_key(): Algorithm %d not suppored\n", in_alg)); return (NULL); } if ((type & (DST_PUBLIC | DST_PRIVATE)) == 0) return (NULL); if (in_keyname == NULL) { EREPORT(("dst_read_private_key(): Null key name passed in\n")); return (NULL); } else if (strlen(in_keyname) >= sizeof(keyname)) { EREPORT(("dst_read_private_key(): keyname too big\n")); return (NULL); } else strcpy(keyname, in_keyname); /* before I read in the public key, check if it is allowed to sign */ if ((pubkey = dst_s_read_public_key(keyname, in_id, in_alg)) == NULL) return (NULL); if (type == DST_PUBLIC) return pubkey; if (!(dg_key = dst_s_get_key_struct(keyname, pubkey->dk_alg, pubkey->dk_flags, pubkey->dk_proto, 0))) return (dg_key); /* Fill in private key and some fields in the general key structure */ if (dst_s_read_private_key_file(keyname, dg_key, pubkey->dk_id, pubkey->dk_alg) == 0) dg_key = dst_free_key(dg_key); (void)dst_free_key(pubkey); return (dg_key); }
/*% * dst_init * This function initializes the Digital Signature Toolkit. * Right now, it just checks the DSTKEYPATH environment variable. * Parameters * none * Returns * none */ void dst_init() { char *s; int len; if (done_init != 0) return; done_init = 1; s = getenv("DSTKEYPATH"); len = 0; if (s) { struct stat statbuf; len = strlen(s); if (len > PATH_MAX) { EREPORT(("%s is longer than %d characters, ignoring\n", s, PATH_MAX)); } else if (stat(s, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) { EREPORT(("%s is not a valid directory\n", s)); } else { char *tmp; tmp = (char *) malloc(len + 2); memcpy(tmp, s, len + 1); if (tmp[strlen(tmp) - 1] != '/') { tmp[strlen(tmp) + 1] = 0; tmp[strlen(tmp)] = '/'; } dst_path = tmp; } } memset(dst_t_func, 0, sizeof(dst_t_func)); /* first one is selected */ dst_hmac_md5_init(); }
int dst_write_key(const DST_KEY *key, const int type) { int pub = 0, priv = 0; if (key == NULL) return (0); if (!dst_check_algorithm(key->dk_alg)) { /*%< make sure alg is available */ EREPORT(("dst_write_key(): Algorithm %d not suppored\n", key->dk_alg)); return (UNSUPPORTED_KEYALG); } if ((type & (DST_PRIVATE|DST_PUBLIC)) == 0) return (0); if (type & DST_PUBLIC) if ((pub = dst_s_write_public_key(key)) < 0) return (pub); if (type & DST_PRIVATE) if ((priv = dst_s_write_private_key(key)) < 0) return (priv); return (priv+pub); }
static DST_KEY * dst_s_read_public_key(const char *in_name, const u_int16_t in_id, int in_alg) { int flags, proto, alg, len, dlen; int c; char name[PATH_MAX], enckey[RAW_KEY_SIZE], *notspace; u_char deckey[RAW_KEY_SIZE]; FILE *fp; if (in_name == NULL) { EREPORT(("dst_read_public_key(): No key name given\n")); return (NULL); } if (dst_s_build_filename(name, in_name, in_id, in_alg, PUBLIC_KEY, PATH_MAX) == -1) { EREPORT(("dst_read_public_key(): Cannot make filename from %s, %d, and %s\n", in_name, in_id, PUBLIC_KEY)); return (NULL); } /* * Open the file and read it's formatted contents up to key * File format: * domain.name [ttl] [IN] KEY <flags> <protocol> <algorithm> <key> * flags, proto, alg stored as decimal (or hex numbers FIXME). * (FIXME: handle parentheses for line continuation.) */ if ((fp = dst_s_fopen(name, "r", 0)) == NULL) { EREPORT(("dst_read_public_key(): Public Key not found %s\n", name)); return (NULL); } /* Skip domain name, which ends at first blank */ while ((c = getc(fp)) != EOF) if (isspace(c)) break; /* Skip blank to get to next field */ while ((c = getc(fp)) != EOF) if (!isspace(c)) break; /* Skip optional TTL -- if initial digit, skip whole word. */ if (isdigit(c)) { while ((c = getc(fp)) != EOF) if (isspace(c)) break; while ((c = getc(fp)) != EOF) if (!isspace(c)) break; } /* Skip optional "IN" */ if (c == 'I' || c == 'i') { while ((c = getc(fp)) != EOF) if (isspace(c)) break; while ((c = getc(fp)) != EOF) if (!isspace(c)) break; } /* Locate and skip "KEY" */ if (c != 'K' && c != 'k') { EREPORT(("\"KEY\" doesn't appear in file: %s", name)); return NULL; } while ((c = getc(fp)) != EOF) if (isspace(c)) break; while ((c = getc(fp)) != EOF) if (!isspace(c)) break; ungetc(c, fp); /*%< return the charcter to the input field */ /* Handle hex!! FIXME. */ if (fscanf(fp, "%d %d %d", &flags, &proto, &alg) != 3) { EREPORT(("dst_read_public_key(): Can not read flag/proto/alg field from %s\n" ,name)); return (NULL); } /* read in the key string */ fgets(enckey, sizeof(enckey), fp); /* If we aren't at end-of-file, something is wrong. */ while ((c = getc(fp)) != EOF) if (!isspace(c)) break; if (!feof(fp)) { EREPORT(("Key too long in file: %s", name)); return NULL; } fclose(fp); if ((len = strlen(enckey)) <= 0) return (NULL); /* discard \n */ enckey[--len] = '\0'; /* remove leading spaces */ for (notspace = (char *) enckey; isspace((*notspace)&0xff); len--) notspace++; dlen = b64_pton(notspace, deckey, sizeof(deckey)); if (dlen < 0) { EREPORT(("dst_read_public_key: bad return from b64_pton = %d", dlen)); return (NULL); } /* store key and info in a key structure that is returned */ /* return dst_store_public_key(in_name, alg, proto, 666, flags, deckey, dlen);*/ return dst_buffer_to_key(in_name, alg, flags, proto, deckey, dlen); }