/** * @brief Get a placer pointing to the text contained within a specified pair of opening and closing braces. * @param str a placer pointing to the string to be parsed. * @param out a pointer to a placer that will store the string between the braces on success. * @param opening the character to be the opening brace of the sequence. * @param closing the character to be the closing brace of the sequence. * @param required if true, fail if no data was found between the pair of braces. * @return true if the brace sequence was complete, or false if either component could not be located. */ bool_t pl_get_embraced (placer_t str, placer_t *out, unsigned char opening, unsigned char closing, bool_t required) { char *ptr = pl_char_get(str); if (pl_empty(str)) { return false; } // Must have at least 2 characters for the opening and closing if (str.length < 2) { return false; } else if (*ptr != opening) { return false; } ptr++; for (int i = 1; i < str.length; i++, ptr++) { if (*ptr == closing) { if (required && i <= 1) { return false; } out->data = pl_char_get(str) + 1; out->length = i - 1; return true; } } // We hit the end without finding a closing character... return false; }
/** * @brief Truncate a placer to start before any of the specified characters, and update the placer accordingly. * @param place a pointer to a placer that will be updated to be truncated before any of the specified characters. * @param shrinkchars a pointer to a buffer containing bytes that will be skipped when they are found at the end of the placer. * @param nchars the number of characters to be tested in the collection in shrinkchars. * @return true if the shrink operation completed before the end of the placer was reached, or false otherwise. */ bool_t pl_shrink_before_characters (placer_t *place, char *shrinkchars, size_t nchars) { char *ptr = pl_char_get(*place) + pl_length_get(*place) - 1; if (pl_empty(*place)) { return false; } for (int i = 0; i < place->length; i++, ptr--) { for (int j = 0; j <= nchars; j++) { // We went through all the skip characters without finding something... so this is where we return. if (j == nchars) { place->length -= i; return true; } if (*ptr == shrinkchars[j]) break; } } return false; }
/** * @brief Skip to the first instance of any of the specified characters in the placer, and update the placer accordingly. * @param place a pointer to a placer that will be updated to skip to any of the specified characters. * @param skiptochars a pointer to a buffer containing bytes that will be skipped to when they are first found in the placer. * @param nchars the number of characters to be tested in the collection in skiptochars. * @return true if the skip operation completed before the end of the placer was reached, or false otherwise. */ bool_t pl_skip_to_characters (placer_t *place, char *skiptochars, size_t nchars) { char *ptr = pl_char_get(*place); if (pl_empty(*place)) { return false; } for (int i = 0; i < place->length; i++, ptr++) { for (int j = 0; j < nchars; j++) { // We went through all the skip characters without finding something... so this is where we return. if (*ptr == skiptochars[j]) { place->data = (char *) place->data + i; place->length -= i; return true; } } } return false; }
/** * @brief Retrieve a specified string-split token from a null-terminated string. * @param block a pointer to the block of memory to be tokenized. * @param length the maximum number of characters to be scanned from the input data. * @param token the token string that will be used to split the data. * @param toklen the length, in bytes, of the token string. * @param fragment the zero-indexed token number to be extracted from the data. * @param value a pointer to a placer that will receive the value of the extracted token on success, or pl_null() on failure. * @return -1 on failure, 0 on success, or 1 if the token was extracted successfully, but was the last one in the string. */ int str_tok_get_bl(char *block, size_t length, chr_t *token, size_t toklen, uint64_t fragment, placer_t *value) { placer_t haystack, needle; size_t hptr, skipped = 0; bool_t found; // We can't search NULL pointers or empty strings. if (!value || mm_empty(block, length) || mm_empty(token, toklen)) { *value = pl_null(); return -1; } haystack = pl_init(block, length); needle = pl_init(token, toklen); while (fragment) { if (!(found = st_search_cs(&haystack, &needle, &hptr))) { *value = pl_null(); return -1; } // Haystack becomes the entire block after the token. skipped += pl_length_get (needle) + hptr; haystack = pl_init(pl_char_get(haystack) + skipped, length-skipped); fragment--; } // If no more tokens are present, return everything we have left if (!st_search_cs(&haystack, &needle, &hptr)) { *value = haystack; return 1; } *value = pl_init(pl_char_get(haystack), hptr); return 0; }
EC_KEY * deprecated_ecies_key_private(uint64_t format, placer_t data) { EC_KEY *key = NULL; BIGNUM *number = NULL; if (!(key = deprecated_ecies_key_alloc())) { log_info("Unable to allocate an empty key context."); return NULL; } // Process a key in binary format. if (format & ECIES_PRIVATE_BINARY) { if (!(number = BN_bin2bn_d(pl_data_get(data), pl_length_get(data), NULL))) { log_info("An error occurred while parsing the binary elliptical curve point data used to represent the private key. {%s}", ssl_error_string(MEMORYBUF(256), 256)); EC_KEY_free_d(key); return NULL; } } // Process a key in hex. else if (format & ECIES_PRIVATE_HEX) { if (!(BN_hex2bn_d(&number, pl_char_get(data)))) { log_info("An error occurred while parsing the binary elliptical curve point data used to represent the private key. {%s}", ssl_error_string(MEMORYBUF(256), 256)); EC_KEY_free_d(key); return NULL; } } // Invalid format! else { log_info("The private key data is using an unrecognized format."); EC_KEY_free_d(key); return NULL; } // Assign the point to our empty key instance. if (EC_KEY_set_private_key_d(key, number) != 1) { log_info("The provided point data does not represent a valid public key. {%s}", ssl_error_string(MEMORYBUF(256), 256)); EC_KEY_free_d(key); BN_free_d(number); return NULL; } // The above function call duplicates the point so the local copy is no longer needed. BN_free_d(number); return key; }
EC_KEY * deprecated_ecies_key_public(uint64_t format, placer_t data) { EC_KEY *key = NULL; EC_POINT *point = NULL; if (!(key = deprecated_ecies_key_alloc())) { log_info("Unable to allocate an empty key context."); return NULL; } // Process a key in binary format. if (format & ECIES_PUBLIC_BINARY) { // Generate the empty point context we'll be assigning to below. if (!(point = EC_POINT_new_d(EC_KEY_get0_group_d(key)))) { log_info("An error occurred while allocate the elliptical curve point. {%s}", ssl_error_string(MEMORYBUF(256), 256)); EC_KEY_free_d(key); return NULL; } else if (EC_POINT_oct2point_d(EC_KEY_get0_group_d(key), point, pl_data_get(data), pl_length_get(data), NULL) != 1) { log_info("An error occurred while parsing the binary elliptical curve point data used to represent the public key. {%s}", ssl_error_string(MEMORYBUF(256), 256)); EC_POINT_free_d(point); EC_KEY_free_d(key); return NULL; } } // Process a key in hex. else if (format & ECIES_PUBLIC_HEX) { if (!(point = EC_POINT_hex2point_d(EC_KEY_get0_group_d(key), pl_char_get(data), NULL, NULL))) { log_info("An error occurred while parsing the binary elliptical curve point data used to represent the public key. {%s}", ssl_error_string(MEMORYBUF(256), 256)); EC_KEY_free_d(key); return NULL; } } // Invalid format! else { log_info("The public key data is using an unrecognized format."); EC_POINT_free_d(point); EC_KEY_free_d(key); return NULL; } // Assign the point to our empty key instance. if (EC_KEY_set_public_key_d(key, point) != 1) { log_info("The provided point data does not represent a valid public key. {%s}", ssl_error_string(MEMORYBUF(256), 256)); EC_POINT_free_d(point); EC_KEY_free_d(key); return NULL; } // The above function call duplicates the point so the local copy is no longer needed. EC_POINT_free_d(point); // Ensures the provided point is along the active elliptical curve and therefore represents a valid public key. if (EC_KEY_check_key_d(key) != 1) { log_info("The provided point data does not represent a valid public key. {%s}", ssl_error_string(MEMORYBUF(256), 256)); EC_KEY_free_d(key); return NULL; } return key; }
/** * @brief Get a placer pointing to the specified line ('\n' delimited) of another placer. * @param string a pointer to the placer to be scanned. * @param number the zero-based index of the line to be retrieved from the placer. * @return a null placer on failure, or a placer pointing to the specified line on success. */ placer_t line_pl_pl(placer_t string, uint64_t number) { return line_pl_bl(pl_char_get(string), pl_length_get(string), number); }
/** * @brief Return a zero-length placer pointing to NULL data. * @return a zero-length placer pointing to NULL data. */ placer_t pl_null(void) { return (placer_t){ .opts = PLACER_T | JOINTED | STACK | FOREIGNDATA, .data = NULL, .length = 0 }; } /** * @brief Return a placer wrapping a data buffer of given size. * @param data a pointer to the data to be wrapped. * @param len the length, in bytes, of the data. * @return a placer pointing to the specified data. */ placer_t pl_init(void *data, size_t len) { return (placer_t){ .opts = PLACER_T | JOINTED | STACK | FOREIGNDATA, .data = data, .length = len }; } placer_t pl_clone(placer_t place) { return (pl_init(place.data, place.length)); } placer_t pl_set(placer_t place, placer_t set) { return (placer_t){ .opts = place.opts, .data = set.data, .length = set.length }; } /** * @brief Get a pointer to the data referenced by a placer. * @param place the input placer. * @return NULL on failure or a pointer to the block of data associated with the specified placer on success. */ void * pl_data_get(placer_t place) { return st_data_get((stringer_t *)&place); } /** * @brief Get a character pointer to the data referenced by a placer. * @param place the input placer. * @return NULL on failure or a a character pointer to the block of data associated with the specified placer on success. */ chr_t * pl_char_get(placer_t place) { return st_char_get((stringer_t *)&place); } /** * @brief Get the length, in bytes, of a placer as an integer. * @param place the input placer. * @return the size, in bytes, of the specified placer. */ int_t pl_length_int(placer_t place) { return st_length_int((stringer_t *)&place); } /** * @brief Get the length, in bytes, of a placer. * @param place the input placer. * @return the size, in bytes, of the specified placer. */ size_t pl_length_get(placer_t place) { return st_length_get((stringer_t *)&place); } /** * @brief Determine whether or not the specified placer is empty. * @param place the input placer. * @return true if the placer is empty or zero-length, or false otherwise. */ bool_t pl_empty(placer_t place) { return st_empty((stringer_t *)&place); } /** * @brief Determine if a placer begins with a specified character. * @param place the input placer. * @param c the character to be compared with the first byte of the placer's data. * @return true if the placer begins with the given character or false otherwise. */ bool_t pl_starts_with_char(placer_t place, chr_t c) { if (pl_empty(place)) { return false; } if (*(pl_char_get(place)) == c) { return true; } return false; } /** * @brief Advance the placer one character forward beyond an expected character. * @param place the input placer. * @param more if true, the placer must contain more data, and vice versa. * @return true if more was true and the placer contains more data, or if more was false and the placer ended; false otherwise. */ bool_t pl_inc(placer_t *place, bool_t more) { if (pl_empty(*place)) { return false; } place->length--; place->data = (chr_t *)place->data + 1; return (more == (place->length > 0)); }