/* * rotn_decrypt -- * A simple decryption example that passes data through unchanged. */ static int rotn_decrypt(WT_ENCRYPTOR *encryptor, WT_SESSION *session, uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len, size_t *result_lenp) { ROTN_ENCRYPTOR *rotn_encryptor = (ROTN_ENCRYPTOR *)encryptor; size_t mylen; uint32_t i; (void)session; /* Unused */ /* * For certain tests, force an error we can recognize. */ if (rotn_encryptor->force_error) return (-1000); /* * Make sure it is big enough. */ mylen = src_len - (CHKSUM_LEN + IV_LEN); if (dst_len < mylen) return (rotn_error(rotn_encryptor, session, ENOMEM, "decrypt buffer not big enough")); /* * !!! Most implementations would verify the checksum here. */ /* * Copy the encrypted data to the destination buffer and then * decrypt the destination buffer. */ i = CHKSUM_LEN + IV_LEN; memcpy(&dst[0], &src[i], mylen); /* * Depending on whether we have a secret key or not, * call the common rotate or shift function on the text portion * of the destination buffer. Send in dst_len as the length of * the text. */ /* * !!! Most implementations would need the IV too. */ if (rotn_encryptor->shift_len == 0) do_rotate((char *)dst, mylen, 26 - rotn_encryptor->rot_N); else do_shift(&dst[0], mylen, rotn_encryptor->shift_back, rotn_encryptor->shift_len); *result_lenp = mylen; return (0); }
/* * rotn_configure -- * WiredTiger no-op encryption configuration. */ static int rotn_configure(ROTN_ENCRYPTOR *rotn_encryptor, WT_CONFIG_ARG *config) { WT_CONFIG_ITEM v; WT_EXTENSION_API *wt_api; /* Extension API */ int ret; wt_api = rotn_encryptor->wt_api; /* Get the configuration string. */ if ((ret = wt_api->config_get( wt_api, NULL, config, "rotn_force_error", &v)) == 0) rotn_encryptor->force_error = v.val != 0; else if (ret != WT_NOTFOUND) return (rotn_error(rotn_encryptor, NULL, EINVAL, "error parsing config")); return (0); }
/* * rotn_encrypt -- * A simple encryption example that passes data through unchanged. */ static int rotn_encrypt(WT_ENCRYPTOR *encryptor, WT_SESSION *session, uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len, size_t *result_lenp) { ROTN_ENCRYPTOR *rotn_encryptor = (ROTN_ENCRYPTOR *)encryptor; uint32_t i; (void)session; /* Unused */ if (dst_len < src_len + CHKSUM_LEN + IV_LEN) return (rotn_error(rotn_encryptor, session, ENOMEM, "encrypt buffer not big enough")); /* * !!! Most implementations would verify any needed * checksum and initialize the IV here. */ i = CHKSUM_LEN + IV_LEN; memcpy(&dst[i], &src[0], src_len); /* * Depending on whether we have a secret key or not, * call the common rotate or shift function on the text portion * of the destination buffer. Send in src_len as the length of * the text. */ if (rotn_encryptor->shift_len == 0) do_rotate((char *)dst + i, src_len, rotn_encryptor->rot_N); else do_shift(&dst[i], src_len, rotn_encryptor->shift_forw, rotn_encryptor->shift_len); /* * Checksum the encrypted buffer and add the IV. */ i = 0; make_checksum(&dst[i]); i += CHKSUM_LEN; make_iv(&dst[i]); *result_lenp = dst_len; return (0); }
/* * 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 *wt_api; size_t i, len; int ret, keyid_val; u_char base; ret = 0; keyid_val = 0; orig = (const ROTN_ENCRYPTOR *)encryptor; wt_api = orig->wt_api; 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 = wt_api->config_get(wt_api, 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 = rotn_error(rotn_encryptor, NULL, EINVAL, "rotn_customize: invalid keyid"); 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 = wt_api->config_get(wt_api, 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 = rotn_error(rotn_encryptor, NULL, EINVAL, "rotn_customize: invalid key"); 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); }