/* * rotn_configure -- * WiredTiger no-op encryption configuration. */ static int rotn_configure(ROTN_ENCRYPTOR *rotn_encryptor, WT_CONFIG_ARG *config) { WT_CONFIG_ITEM k, v; WT_CONFIG_PARSER *config_parser; WT_EXTENSION_API *wtext; /* Extension API */ int ret, t_ret; wtext = rotn_encryptor->wtext; /* Get the configuration string. */ if ((ret = wtext->config_get(wtext, NULL, config, "config", &v)) != 0) return (rotn_error(rotn_encryptor, NULL, ret, "WT_EXTENSION_API.config_get")); /* Step through the list of configuration options. */ if ((ret = wtext->config_parser_open( wtext, NULL, v.str, v.len, &config_parser)) != 0) return (rotn_error(rotn_encryptor, NULL, ret, "WT_EXTENSION_API.config_parser_open")); while ((ret = config_parser->next(config_parser, &k, &v)) == 0) { if (strncmp("rotn_force_error", k.str, k.len) == 0 && strlen("rotn_force_error") == k.len) { rotn_encryptor->force_error = v.val == 0 ? 0 : 1; continue; } else { if ((ret = config_parser->close(config_parser)) != 0) return (rotn_error(rotn_encryptor, NULL, ret, "WT_CONFIG_PARSER.close")); return (rotn_error(rotn_encryptor, NULL, EINVAL, "unknown config key")); } } if ((t_ret = config_parser->close(config_parser)) != 0) return (rotn_error(rotn_encryptor, NULL, t_ret, "WT_CONFIG_PARSER.close")); if (ret != WT_NOTFOUND) return (rotn_error(rotn_encryptor, NULL, ret, "WT_CONFIG_PARSER.next")); return (0); }
/* * rotn_customize -- * The customize function creates a customized encryptor */ static int rotn_customize(WT_ENCRYPTOR *encryptor, WT_SESSION *session, WT_CONFIG_ARG *encrypt_config, WT_ENCRYPTOR **customp) { const ROTN_ENCRYPTOR *orig; ROTN_ENCRYPTOR *rotn_encryptor; WT_CONFIG_ITEM keyid, secret; WT_EXTENSION_API *wtext; size_t i, len; int ret, keyid_val; u_char base; ret = 0; keyid_val = 0; orig = (const ROTN_ENCRYPTOR *)encryptor; wtext = orig->wtext; if ((rotn_encryptor = calloc(1, sizeof(ROTN_ENCRYPTOR))) == NULL) return (errno); *rotn_encryptor = *orig; rotn_encryptor->keyid = rotn_encryptor->secretkey = NULL; /* * Stash the keyid from the configuration string. */ if ((ret = wtext->config_get(wtext, session, encrypt_config, "keyid", &keyid)) == 0 && keyid.len != 0) { /* * In this demonstration, we expect keyid to be a number. */ if ((keyid_val = atoi(keyid.str)) < 0) { ret = EINVAL; goto err; } if ((rotn_encryptor->keyid = malloc(keyid.len + 1)) == NULL) { ret = errno; goto err; } strncpy(rotn_encryptor->keyid, keyid.str, keyid.len + 1); rotn_encryptor->keyid[keyid.len] = '\0'; } /* * In this demonstration, the secret key must be alphabetic characters. * We stash the secret key from the configuration string * and build some shift bytes to make encryption/decryption easy. */ if ((ret = wtext->config_get(wtext, session, encrypt_config, "secretkey", &secret)) == 0 && secret.len != 0) { len = secret.len; if ((rotn_encryptor->secretkey = malloc(len + 1)) == NULL || (rotn_encryptor->shift_forw = malloc(len)) == NULL || (rotn_encryptor->shift_back = malloc(len)) == NULL) { ret = errno; goto err; } for (i = 0; i < len; i++) { if ('a' <= secret.str[i] && secret.str[i] <= 'z') base = 'a'; else if ('A' <= secret.str[i] && secret.str[i] <= 'Z') base = 'A'; else { ret = EINVAL; goto err; } base -= (u_char)keyid_val; rotn_encryptor->shift_forw[i] = (u_char)secret.str[i] - base; rotn_encryptor->shift_back[i] = base - (u_char)secret.str[i]; } rotn_encryptor->shift_len = len; strncpy(rotn_encryptor->secretkey, secret.str, secret.len + 1); rotn_encryptor->secretkey[secret.len] = '\0'; } /* * In a real encryptor, we could use some sophisticated key management * here to map the keyid onto a secret key. */ rotn_encryptor->rot_N = keyid_val; *customp = (WT_ENCRYPTOR *)rotn_encryptor; return (0); err: free(rotn_encryptor->keyid); free(rotn_encryptor->secretkey); free(rotn_encryptor->shift_forw); free(rotn_encryptor->shift_back); free(rotn_encryptor); return (ret); }
/* * rotate_customize -- * The customize function creates a customized encryptor */ static int rotate_customize(WT_ENCRYPTOR *encryptor, WT_SESSION *session, WT_CONFIG_ARG *encrypt_config, WT_ENCRYPTOR **customp) { MY_CRYPTO *my_crypto; WT_CONFIG_ITEM keyid, secret; WT_EXTENSION_API *extapi; int ret; const MY_CRYPTO *orig_crypto; extapi = session->connection->get_extension_api(session->connection); orig_crypto = (const MY_CRYPTO *)encryptor; if ((my_crypto = calloc(1, sizeof(MY_CRYPTO))) == NULL) { ret = errno; goto err; } *my_crypto = *orig_crypto; my_crypto->keyid = my_crypto->password = NULL; /* * Stash the keyid and the (optional) secret key from the configuration * string. */ error_check(extapi->config_get( extapi, session, encrypt_config, "keyid", &keyid)); if (keyid.len != 0) { if ((my_crypto->keyid = malloc(keyid.len + 1)) == NULL) { ret = errno; goto err; } strncpy(my_crypto->keyid, keyid.str, keyid.len + 1); my_crypto->keyid[keyid.len] = '\0'; } ret = extapi->config_get( extapi, session, encrypt_config, "secretkey", &secret); if (ret == 0 && secret.len != 0) { if ((my_crypto->password = malloc(secret.len + 1)) == NULL) { ret = errno; goto err; } strncpy(my_crypto->password, secret.str, secret.len + 1); my_crypto->password[secret.len] = '\0'; } /* * Presumably we'd have some sophisticated key management * here that maps the id onto a secret key. */ if (ITEM_MATCHES(keyid, "system")) { if (my_crypto->password == NULL || strcmp(my_crypto->password, SYS_PW) != 0) { ret = EPERM; goto err; } my_crypto->rot_N = 13; } else if (ITEM_MATCHES(keyid, USER1_KEYID)) my_crypto->rot_N = 4; else if (ITEM_MATCHES(keyid, USER2_KEYID)) my_crypto->rot_N = 19; else { ret = EINVAL; goto err; } ++my_crypto->num_calls; /* Call count */ *customp = (WT_ENCRYPTOR *)my_crypto; return (0); err: free(my_crypto->keyid); free(my_crypto->password); free(my_crypto); return (ret); }