Move files around to new directory structure

This commit is contained in:
jakcron
2022-04-13 13:28:31 +08:00
parent 5840526951
commit 9b5ec5a4b7
113 changed files with 1 additions and 1 deletions
+19
View File
@@ -0,0 +1,19 @@
Copyright (c) 2006 Kirill Simonov
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
File diff suppressed because it is too large Load Diff
+394
View File
@@ -0,0 +1,394 @@
#include "libyaml/yaml_private.h"
/*
* API functions.
*/
YAML_DECLARE(int)
yaml_emitter_open(yaml_emitter_t *emitter);
YAML_DECLARE(int)
yaml_emitter_close(yaml_emitter_t *emitter);
YAML_DECLARE(int)
yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document);
/*
* Clean up functions.
*/
static void
yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter);
/*
* Anchor functions.
*/
static void
yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index);
static yaml_char_t *
yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id);
/*
* Serialize functions.
*/
static int
yaml_emitter_dump_node(yaml_emitter_t *emitter, int index);
static int
yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor);
static int
yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
yaml_char_t *anchor);
static int
yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
yaml_char_t *anchor);
static int
yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
yaml_char_t *anchor);
/*
* Issue a STREAM-START event.
*/
YAML_DECLARE(int)
yaml_emitter_open(yaml_emitter_t *emitter)
{
yaml_event_t event;
yaml_mark_t mark = { 0, 0, 0 };
assert(emitter); /* Non-NULL emitter object is required. */
assert(!emitter->opened); /* Emitter should not be opened yet. */
STREAM_START_EVENT_INIT(event, YAML_ANY_ENCODING, mark, mark);
if (!yaml_emitter_emit(emitter, &event)) {
return 0;
}
emitter->opened = 1;
return 1;
}
/*
* Issue a STREAM-END event.
*/
YAML_DECLARE(int)
yaml_emitter_close(yaml_emitter_t *emitter)
{
yaml_event_t event;
yaml_mark_t mark = { 0, 0, 0 };
assert(emitter); /* Non-NULL emitter object is required. */
assert(emitter->opened); /* Emitter should be opened. */
if (emitter->closed) return 1;
STREAM_END_EVENT_INIT(event, mark, mark);
if (!yaml_emitter_emit(emitter, &event)) {
return 0;
}
emitter->closed = 1;
return 1;
}
/*
* Dump a YAML document.
*/
YAML_DECLARE(int)
yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document)
{
yaml_event_t event;
yaml_mark_t mark = { 0, 0, 0 };
assert(emitter); /* Non-NULL emitter object is required. */
assert(document); /* Non-NULL emitter object is expected. */
emitter->document = document;
if (!emitter->opened) {
if (!yaml_emitter_open(emitter)) goto error;
}
if (STACK_EMPTY(emitter, document->nodes)) {
if (!yaml_emitter_close(emitter)) goto error;
yaml_emitter_delete_document_and_anchors(emitter);
return 1;
}
assert(emitter->opened); /* Emitter should be opened. */
emitter->anchors = yaml_malloc(sizeof(*(emitter->anchors))
* (document->nodes.top - document->nodes.start));
if (!emitter->anchors) goto error;
memset(emitter->anchors, 0, sizeof(*(emitter->anchors))
* (document->nodes.top - document->nodes.start));
DOCUMENT_START_EVENT_INIT(event, document->titleVersion_directive,
document->tag_directives.start, document->tag_directives.end,
document->start_implicit, mark, mark);
if (!yaml_emitter_emit(emitter, &event)) goto error;
yaml_emitter_anchor_node(emitter, 1);
if (!yaml_emitter_dump_node(emitter, 1)) goto error;
DOCUMENT_END_EVENT_INIT(event, document->end_implicit, mark, mark);
if (!yaml_emitter_emit(emitter, &event)) goto error;
yaml_emitter_delete_document_and_anchors(emitter);
return 1;
error:
yaml_emitter_delete_document_and_anchors(emitter);
return 0;
}
/*
* Clean up the emitter object after a document is dumped.
*/
static void
yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter)
{
int index;
if (!emitter->anchors) {
yaml_document_delete(emitter->document);
emitter->document = NULL;
return;
}
for (index = 0; emitter->document->nodes.start + index
< emitter->document->nodes.top; index ++) {
yaml_node_t node = emitter->document->nodes.start[index];
if (!emitter->anchors[index].serialized) {
yaml_free(node.tag);
if (node.type == YAML_SCALAR_NODE) {
yaml_free(node.data.scalar.value);
}
}
if (node.type == YAML_SEQUENCE_NODE) {
STACK_DEL(emitter, node.data.sequence.items);
}
if (node.type == YAML_MAPPING_NODE) {
STACK_DEL(emitter, node.data.mapping.pairs);
}
}
STACK_DEL(emitter, emitter->document->nodes);
yaml_free(emitter->anchors);
emitter->anchors = NULL;
emitter->last_anchor_id = 0;
emitter->document = NULL;
}
/*
* Check the references of a node and assign the anchor id if needed.
*/
static void
yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index)
{
yaml_node_t *node = emitter->document->nodes.start + index - 1;
yaml_node_item_t *item;
yaml_node_pair_t *pair;
emitter->anchors[index-1].references ++;
if (emitter->anchors[index-1].references == 1) {
switch (node->type) {
case YAML_SEQUENCE_NODE:
for (item = node->data.sequence.items.start;
item < node->data.sequence.items.top; item ++) {
yaml_emitter_anchor_node(emitter, *item);
}
break;
case YAML_MAPPING_NODE:
for (pair = node->data.mapping.pairs.start;
pair < node->data.mapping.pairs.top; pair ++) {
yaml_emitter_anchor_node(emitter, pair->key);
yaml_emitter_anchor_node(emitter, pair->value);
}
break;
default:
break;
}
}
else if (emitter->anchors[index-1].references == 2) {
emitter->anchors[index-1].anchor = (++ emitter->last_anchor_id);
}
}
/*
* Generate a textual representation for an anchor.
*/
#define ANCHOR_TEMPLATE "id%03d"
#define ANCHOR_TEMPLATE_LENGTH 16
static yaml_char_t *
yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id)
{
yaml_char_t *anchor = yaml_malloc(ANCHOR_TEMPLATE_LENGTH);
if (!anchor) return NULL;
sprintf((char *)anchor, ANCHOR_TEMPLATE, anchor_id);
return anchor;
}
/*
* Serialize a node.
*/
static int
yaml_emitter_dump_node(yaml_emitter_t *emitter, int index)
{
yaml_node_t *node = emitter->document->nodes.start + index - 1;
int anchor_id = emitter->anchors[index-1].anchor;
yaml_char_t *anchor = NULL;
if (anchor_id) {
anchor = yaml_emitter_generate_anchor(emitter, anchor_id);
if (!anchor) return 0;
}
if (emitter->anchors[index-1].serialized) {
return yaml_emitter_dump_alias(emitter, anchor);
}
emitter->anchors[index-1].serialized = 1;
switch (node->type) {
case YAML_SCALAR_NODE:
return yaml_emitter_dump_scalar(emitter, node, anchor);
case YAML_SEQUENCE_NODE:
return yaml_emitter_dump_sequence(emitter, node, anchor);
case YAML_MAPPING_NODE:
return yaml_emitter_dump_mapping(emitter, node, anchor);
default:
assert(0); /* Could not happen. */
break;
}
return 0; /* Could not happen. */
}
/*
* Serialize an alias.
*/
static int
yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor)
{
yaml_event_t event;
yaml_mark_t mark = { 0, 0, 0 };
ALIAS_EVENT_INIT(event, anchor, mark, mark);
return yaml_emitter_emit(emitter, &event);
}
/*
* Serialize a scalar.
*/
static int
yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
yaml_char_t *anchor)
{
yaml_event_t event;
yaml_mark_t mark = { 0, 0, 0 };
int plain_implicit = (strcmp((char *)node->tag,
YAML_DEFAULT_SCALAR_TAG) == 0);
int quoted_implicit = (strcmp((char *)node->tag,
YAML_DEFAULT_SCALAR_TAG) == 0);
SCALAR_EVENT_INIT(event, anchor, node->tag, node->data.scalar.value,
node->data.scalar.length, plain_implicit, quoted_implicit,
node->data.scalar.style, mark, mark);
return yaml_emitter_emit(emitter, &event);
}
/*
* Serialize a sequence.
*/
static int
yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
yaml_char_t *anchor)
{
yaml_event_t event;
yaml_mark_t mark = { 0, 0, 0 };
int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_SEQUENCE_TAG) == 0);
yaml_node_item_t *item;
SEQUENCE_START_EVENT_INIT(event, anchor, node->tag, implicit,
node->data.sequence.style, mark, mark);
if (!yaml_emitter_emit(emitter, &event)) return 0;
for (item = node->data.sequence.items.start;
item < node->data.sequence.items.top; item ++) {
if (!yaml_emitter_dump_node(emitter, *item)) return 0;
}
SEQUENCE_END_EVENT_INIT(event, mark, mark);
if (!yaml_emitter_emit(emitter, &event)) return 0;
return 1;
}
/*
* Serialize a mapping.
*/
static int
yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
yaml_char_t *anchor)
{
yaml_event_t event;
yaml_mark_t mark = { 0, 0, 0 };
int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_MAPPING_TAG) == 0);
yaml_node_pair_t *pair;
MAPPING_START_EVENT_INIT(event, anchor, node->tag, implicit,
node->data.mapping.style, mark, mark);
if (!yaml_emitter_emit(emitter, &event)) return 0;
for (pair = node->data.mapping.pairs.start;
pair < node->data.mapping.pairs.top; pair ++) {
if (!yaml_emitter_dump_node(emitter, pair->key)) return 0;
if (!yaml_emitter_dump_node(emitter, pair->value)) return 0;
}
MAPPING_END_EVENT_INIT(event, mark, mark);
if (!yaml_emitter_emit(emitter, &event)) return 0;
return 1;
}
File diff suppressed because it is too large Load Diff
+432
View File
@@ -0,0 +1,432 @@
#include "libyaml/yaml_private.h"
/*
* API functions.
*/
YAML_DECLARE(int)
yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);
/*
* Error handling.
*/
static int
yaml_parser_set_composer_error(yaml_parser_t *parser,
const char *problem, yaml_mark_t problem_mark);
static int
yaml_parser_set_composer_error_context(yaml_parser_t *parser,
const char *context, yaml_mark_t context_mark,
const char *problem, yaml_mark_t problem_mark);
/*
* Alias handling.
*/
static int
yaml_parser_register_anchor(yaml_parser_t *parser,
int index, yaml_char_t *anchor);
/*
* Clean up functions.
*/
static void
yaml_parser_delete_aliases(yaml_parser_t *parser);
/*
* Composer functions.
*/
static int
yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event);
static int
yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event);
static int
yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event);
static int
yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event);
static int
yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event);
static int
yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event);
/*
* Load the next document of the stream.
*/
YAML_DECLARE(int)
yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document)
{
yaml_event_t event;
assert(parser); /* Non-NULL parser object is expected. */
assert(document); /* Non-NULL document object is expected. */
memset(document, 0, sizeof(yaml_document_t));
if (!STACK_INIT(parser, document->nodes, INITIAL_STACK_SIZE))
goto error;
if (!parser->stream_start_produced) {
if (!yaml_parser_parse(parser, &event)) goto error;
assert(event.type == YAML_STREAM_START_EVENT);
/* STREAM-START is expected. */
}
if (parser->stream_end_produced) {
return 1;
}
if (!yaml_parser_parse(parser, &event)) goto error;
if (event.type == YAML_STREAM_END_EVENT) {
return 1;
}
if (!STACK_INIT(parser, parser->aliases, INITIAL_STACK_SIZE))
goto error;
parser->document = document;
if (!yaml_parser_load_document(parser, &event)) goto error;
yaml_parser_delete_aliases(parser);
parser->document = NULL;
return 1;
error:
yaml_parser_delete_aliases(parser);
yaml_document_delete(document);
parser->document = NULL;
return 0;
}
/*
* Set composer error.
*/
static int
yaml_parser_set_composer_error(yaml_parser_t *parser,
const char *problem, yaml_mark_t problem_mark)
{
parser->error = YAML_COMPOSER_ERROR;
parser->problem = problem;
parser->problem_mark = problem_mark;
return 0;
}
/*
* Set composer error with context.
*/
static int
yaml_parser_set_composer_error_context(yaml_parser_t *parser,
const char *context, yaml_mark_t context_mark,
const char *problem, yaml_mark_t problem_mark)
{
parser->error = YAML_COMPOSER_ERROR;
parser->context = context;
parser->context_mark = context_mark;
parser->problem = problem;
parser->problem_mark = problem_mark;
return 0;
}
/*
* Delete the stack of aliases.
*/
static void
yaml_parser_delete_aliases(yaml_parser_t *parser)
{
while (!STACK_EMPTY(parser, parser->aliases)) {
yaml_free(POP(parser, parser->aliases).anchor);
}
STACK_DEL(parser, parser->aliases);
}
/*
* Compose a document object.
*/
static int
yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event)
{
yaml_event_t event;
assert(first_event->type == YAML_DOCUMENT_START_EVENT);
/* DOCUMENT-START is expected. */
parser->document->titleVersion_directive
= first_event->data.document_start.titleVersion_directive;
parser->document->tag_directives.start
= first_event->data.document_start.tag_directives.start;
parser->document->tag_directives.end
= first_event->data.document_start.tag_directives.end;
parser->document->start_implicit
= first_event->data.document_start.implicit;
parser->document->start_mark = first_event->start_mark;
if (!yaml_parser_parse(parser, &event)) return 0;
if (!yaml_parser_load_node(parser, &event)) return 0;
if (!yaml_parser_parse(parser, &event)) return 0;
assert(event.type == YAML_DOCUMENT_END_EVENT);
/* DOCUMENT-END is expected. */
parser->document->end_implicit = event.data.document_end.implicit;
parser->document->end_mark = event.end_mark;
return 1;
}
/*
* Compose a node.
*/
static int
yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event)
{
switch (first_event->type) {
case YAML_ALIAS_EVENT:
return yaml_parser_load_alias(parser, first_event);
case YAML_SCALAR_EVENT:
return yaml_parser_load_scalar(parser, first_event);
case YAML_SEQUENCE_START_EVENT:
return yaml_parser_load_sequence(parser, first_event);
case YAML_MAPPING_START_EVENT:
return yaml_parser_load_mapping(parser, first_event);
default:
assert(0); /* Could not happen. */
return 0;
}
return 0;
}
/*
* Add an anchor.
*/
static int
yaml_parser_register_anchor(yaml_parser_t *parser,
int index, yaml_char_t *anchor)
{
yaml_alias_data_t data;
yaml_alias_data_t *alias_data;
if (!anchor) return 1;
data.anchor = anchor;
data.index = index;
data.mark = parser->document->nodes.start[index-1].start_mark;
for (alias_data = parser->aliases.start;
alias_data != parser->aliases.top; alias_data ++) {
if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
yaml_free(anchor);
return yaml_parser_set_composer_error_context(parser,
"found duplicate anchor; first occurence",
alias_data->mark, "second occurence", data.mark);
}
}
if (!PUSH(parser, parser->aliases, data)) {
yaml_free(anchor);
return 0;
}
return 1;
}
/*
* Compose a node corresponding to an alias.
*/
static int
yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event)
{
yaml_char_t *anchor = first_event->data.alias.anchor;
yaml_alias_data_t *alias_data;
for (alias_data = parser->aliases.start;
alias_data != parser->aliases.top; alias_data ++) {
if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
yaml_free(anchor);
return alias_data->index;
}
}
yaml_free(anchor);
return yaml_parser_set_composer_error(parser, "found undefined alias",
first_event->start_mark);
}
/*
* Compose a scalar node.
*/
static int
yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event)
{
yaml_node_t node;
int index;
yaml_char_t *tag = first_event->data.scalar.tag;
if (!tag || strcmp((char *)tag, "!") == 0) {
yaml_free(tag);
tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
if (!tag) goto error;
}
SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value,
first_event->data.scalar.length, first_event->data.scalar.style,
first_event->start_mark, first_event->end_mark);
if (!PUSH(parser, parser->document->nodes, node)) goto error;
index = parser->document->nodes.top - parser->document->nodes.start;
if (!yaml_parser_register_anchor(parser, index,
first_event->data.scalar.anchor)) return 0;
return index;
error:
yaml_free(tag);
yaml_free(first_event->data.scalar.anchor);
yaml_free(first_event->data.scalar.value);
return 0;
}
/*
* Compose a sequence node.
*/
static int
yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event)
{
yaml_event_t event;
yaml_node_t node;
struct {
yaml_node_item_t *start;
yaml_node_item_t *end;
yaml_node_item_t *top;
} items = { NULL, NULL, NULL };
int index, item_index;
yaml_char_t *tag = first_event->data.sequence_start.tag;
if (!tag || strcmp((char *)tag, "!") == 0) {
yaml_free(tag);
tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
if (!tag) goto error;
}
if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error;
SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
first_event->data.sequence_start.style,
first_event->start_mark, first_event->end_mark);
if (!PUSH(parser, parser->document->nodes, node)) goto error;
index = parser->document->nodes.top - parser->document->nodes.start;
if (!yaml_parser_register_anchor(parser, index,
first_event->data.sequence_start.anchor)) return 0;
if (!yaml_parser_parse(parser, &event)) return 0;
while (event.type != YAML_SEQUENCE_END_EVENT) {
item_index = yaml_parser_load_node(parser, &event);
if (!item_index) return 0;
if (!PUSH(parser,
parser->document->nodes.start[index-1].data.sequence.items,
item_index)) return 0;
if (!yaml_parser_parse(parser, &event)) return 0;
}
parser->document->nodes.start[index-1].end_mark = event.end_mark;
return index;
error:
yaml_free(tag);
yaml_free(first_event->data.sequence_start.anchor);
return 0;
}
/*
* Compose a mapping node.
*/
static int
yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
{
yaml_event_t event;
yaml_node_t node;
struct {
yaml_node_pair_t *start;
yaml_node_pair_t *end;
yaml_node_pair_t *top;
} pairs = { NULL, NULL, NULL };
int index;
yaml_node_pair_t pair;
yaml_char_t *tag = first_event->data.mapping_start.tag;
if (!tag || strcmp((char *)tag, "!") == 0) {
yaml_free(tag);
tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
if (!tag) goto error;
}
if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error;
MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
first_event->data.mapping_start.style,
first_event->start_mark, first_event->end_mark);
if (!PUSH(parser, parser->document->nodes, node)) goto error;
index = parser->document->nodes.top - parser->document->nodes.start;
if (!yaml_parser_register_anchor(parser, index,
first_event->data.mapping_start.anchor)) return 0;
if (!yaml_parser_parse(parser, &event)) return 0;
while (event.type != YAML_MAPPING_END_EVENT) {
pair.key = yaml_parser_load_node(parser, &event);
if (!pair.key) return 0;
if (!yaml_parser_parse(parser, &event)) return 0;
pair.value = yaml_parser_load_node(parser, &event);
if (!pair.value) return 0;
if (!PUSH(parser,
parser->document->nodes.start[index-1].data.mapping.pairs,
pair)) return 0;
if (!yaml_parser_parse(parser, &event)) return 0;
}
parser->document->nodes.start[index-1].end_mark = event.end_mark;
return index;
error:
yaml_free(tag);
yaml_free(first_event->data.mapping_start.anchor);
return 0;
}
File diff suppressed because it is too large Load Diff
+465
View File
@@ -0,0 +1,465 @@
#include "libyaml/yaml_private.h"
/*
* Declarations.
*/
static int
yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem,
size_t offset, int value);
static int
yaml_parser_update_raw_buffer(yaml_parser_t *parser);
static int
yaml_parser_determine_encoding(yaml_parser_t *parser);
YAML_DECLARE(int)
yaml_parser_update_buffer(yaml_parser_t *parser, size_t length);
/*
* Set the reader error and return 0.
*/
static int
yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem,
size_t offset, int value)
{
parser->error = YAML_READER_ERROR;
parser->problem = problem;
parser->problem_offset = offset;
parser->problem_value = value;
return 0;
}
/*
* Byte order marks.
*/
#define BOM_UTF8 "\xef\xbb\xbf"
#define BOM_UTF16LE "\xff\xfe"
#define BOM_UTF16BE "\xfe\xff"
/*
* Determine the input stream encoding by checking the BOM symbol. If no BOM is
* found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
*/
static int
yaml_parser_determine_encoding(yaml_parser_t *parser)
{
/* Ensure that we had enough bytes in the raw buffer. */
while (!parser->eof
&& parser->raw_buffer.last - parser->raw_buffer.pointer < 3) {
if (!yaml_parser_update_raw_buffer(parser)) {
return 0;
}
}
/* Determine the encoding. */
if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 2
&& !memcmp(parser->raw_buffer.pointer, BOM_UTF16LE, 2)) {
parser->encoding = YAML_UTF16LE_ENCODING;
parser->raw_buffer.pointer += 2;
parser->offset += 2;
}
else if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 2
&& !memcmp(parser->raw_buffer.pointer, BOM_UTF16BE, 2)) {
parser->encoding = YAML_UTF16BE_ENCODING;
parser->raw_buffer.pointer += 2;
parser->offset += 2;
}
else if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 3
&& !memcmp(parser->raw_buffer.pointer, BOM_UTF8, 3)) {
parser->encoding = YAML_UTF8_ENCODING;
parser->raw_buffer.pointer += 3;
parser->offset += 3;
}
else {
parser->encoding = YAML_UTF8_ENCODING;
}
return 1;
}
/*
* Update the raw buffer.
*/
static int
yaml_parser_update_raw_buffer(yaml_parser_t *parser)
{
size_t size_read = 0;
/* Return if the raw buffer is full. */
if (parser->raw_buffer.start == parser->raw_buffer.pointer
&& parser->raw_buffer.last == parser->raw_buffer.end)
return 1;
/* Return on EOF. */
if (parser->eof) return 1;
/* Move the remaining bytes in the raw buffer to the beginning. */
if (parser->raw_buffer.start < parser->raw_buffer.pointer
&& parser->raw_buffer.pointer < parser->raw_buffer.last) {
memmove(parser->raw_buffer.start, parser->raw_buffer.pointer,
parser->raw_buffer.last - parser->raw_buffer.pointer);
}
parser->raw_buffer.last -=
parser->raw_buffer.pointer - parser->raw_buffer.start;
parser->raw_buffer.pointer = parser->raw_buffer.start;
/* Call the read handler to fill the buffer. */
if (!parser->read_handler(parser->read_handler_data, parser->raw_buffer.last,
parser->raw_buffer.end - parser->raw_buffer.last, &size_read)) {
return yaml_parser_set_reader_error(parser, "input error",
parser->offset, -1);
}
parser->raw_buffer.last += size_read;
if (!size_read) {
parser->eof = 1;
}
return 1;
}
/*
* Ensure that the buffer contains at least `length` characters.
* Return 1 on success, 0 on failure.
*
* The length is supposed to be significantly less that the buffer size.
*/
YAML_DECLARE(int)
yaml_parser_update_buffer(yaml_parser_t *parser, size_t length)
{
int first = 1;
assert(parser->read_handler); /* Read handler must be set. */
/* If the EOF flag is set and the raw buffer is empty, do nothing. */
if (parser->eof && parser->raw_buffer.pointer == parser->raw_buffer.last)
return 1;
/* Return if the buffer contains enough characters. */
if (parser->unread >= length)
return 1;
/* Determine the input encoding if it is not known yet. */
if (!parser->encoding) {
if (!yaml_parser_determine_encoding(parser))
return 0;
}
/* Move the unread characters to the beginning of the buffer. */
if (parser->buffer.start < parser->buffer.pointer
&& parser->buffer.pointer < parser->buffer.last) {
size_t size = parser->buffer.last - parser->buffer.pointer;
memmove(parser->buffer.start, parser->buffer.pointer, size);
parser->buffer.pointer = parser->buffer.start;
parser->buffer.last = parser->buffer.start + size;
}
else if (parser->buffer.pointer == parser->buffer.last) {
parser->buffer.pointer = parser->buffer.start;
parser->buffer.last = parser->buffer.start;
}
/* Fill the buffer until it has enough characters. */
while (parser->unread < length)
{
/* Fill the raw buffer if necessary. */
if (!first || parser->raw_buffer.pointer == parser->raw_buffer.last) {
if (!yaml_parser_update_raw_buffer(parser)) return 0;
}
first = 0;
/* Decode the raw buffer. */
while (parser->raw_buffer.pointer != parser->raw_buffer.last)
{
unsigned int value = 0, value2 = 0;
int incomplete = 0;
unsigned char octet;
unsigned int width = 0;
int low, high;
size_t k;
size_t raw_unread = parser->raw_buffer.last - parser->raw_buffer.pointer;
/* Decode the next character. */
switch (parser->encoding)
{
case YAML_UTF8_ENCODING:
/*
* Decode a UTF-8 character. Check RFC 3629
* (http://www.ietf.org/rfc/rfc3629.txt) for more details.
*
* The following table (taken from the RFC) is used for
* decoding.
*
* Char. number range | UTF-8 octet sequence
* (hexadecimal) | (binary)
* --------------------+------------------------------------
* 0000 0000-0000 007F | 0xxxxxxx
* 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
* 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
* 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
*
* Additionally, the characters in the range 0xD800-0xDFFF
* are prohibited as they are reserved for use with UTF-16
* surrogate pairs.
*/
/* Determine the length of the UTF-8 sequence. */
octet = parser->raw_buffer.pointer[0];
width = (octet & 0x80) == 0x00 ? 1 :
(octet & 0xE0) == 0xC0 ? 2 :
(octet & 0xF0) == 0xE0 ? 3 :
(octet & 0xF8) == 0xF0 ? 4 : 0;
/* Check if the leading octet is valid. */
if (!width)
return yaml_parser_set_reader_error(parser,
"invalid leading UTF-8 octet",
parser->offset, octet);
/* Check if the raw buffer contains an incomplete character. */
if (width > raw_unread) {
if (parser->eof) {
return yaml_parser_set_reader_error(parser,
"incomplete UTF-8 octet sequence",
parser->offset, -1);
}
incomplete = 1;
break;
}
/* Decode the leading octet. */
value = (octet & 0x80) == 0x00 ? octet & 0x7F :
(octet & 0xE0) == 0xC0 ? octet & 0x1F :
(octet & 0xF0) == 0xE0 ? octet & 0x0F :
(octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
/* Check and decode the trailing octets. */
for (k = 1; k < width; k ++)
{
octet = parser->raw_buffer.pointer[k];
/* Check if the octet is valid. */
if ((octet & 0xC0) != 0x80)
return yaml_parser_set_reader_error(parser,
"invalid trailing UTF-8 octet",
parser->offset+k, octet);
/* Decode the octet. */
value = (value << 6) + (octet & 0x3F);
}
/* Check the length of the sequence against the value. */
if (!((width == 1) ||
(width == 2 && value >= 0x80) ||
(width == 3 && value >= 0x800) ||
(width == 4 && value >= 0x10000)))
return yaml_parser_set_reader_error(parser,
"invalid length of a UTF-8 sequence",
parser->offset, -1);
/* Check the range of the value. */
if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF)
return yaml_parser_set_reader_error(parser,
"invalid Unicode character",
parser->offset, value);
break;
case YAML_UTF16LE_ENCODING:
case YAML_UTF16BE_ENCODING:
low = (parser->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
high = (parser->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
/*
* The UTF-16 encoding is not as simple as one might
* naively think. Check RFC 2781
* (http://www.ietf.org/rfc/rfc2781.txt).
*
* Normally, two subsequent bytes describe a Unicode
* character. However a special technique (called a
* surrogate pair) is used for specifying character
* values larger than 0xFFFF.
*
* A surrogate pair consists of two pseudo-characters:
* high surrogate area (0xD800-0xDBFF)
* low surrogate area (0xDC00-0xDFFF)
*
* The following formulas are used for decoding
* and encoding characters using surrogate pairs:
*
* U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
* U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
* W1 = 110110yyyyyyyyyy
* W2 = 110111xxxxxxxxxx
*
* where U is the character value, W1 is the high surrogate
* area, W2 is the low surrogate area.
*/
/* Check for incomplete UTF-16 character. */
if (raw_unread < 2) {
if (parser->eof) {
return yaml_parser_set_reader_error(parser,
"incomplete UTF-16 character",
parser->offset, -1);
}
incomplete = 1;
break;
}
/* Get the character. */
value = parser->raw_buffer.pointer[low]
+ (parser->raw_buffer.pointer[high] << 8);
/* Check for unexpected low surrogate area. */
if ((value & 0xFC00) == 0xDC00)
return yaml_parser_set_reader_error(parser,
"unexpected low surrogate area",
parser->offset, value);
/* Check for a high surrogate area. */
if ((value & 0xFC00) == 0xD800) {
width = 4;
/* Check for incomplete surrogate pair. */
if (raw_unread < 4) {
if (parser->eof) {
return yaml_parser_set_reader_error(parser,
"incomplete UTF-16 surrogate pair",
parser->offset, -1);
}
incomplete = 1;
break;
}
/* Get the next character. */
value2 = parser->raw_buffer.pointer[low+2]
+ (parser->raw_buffer.pointer[high+2] << 8);
/* Check for a low surrogate area. */
if ((value2 & 0xFC00) != 0xDC00)
return yaml_parser_set_reader_error(parser,
"expected low surrogate area",
parser->offset+2, value2);
/* Generate the value of the surrogate pair. */
value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF);
}
else {
width = 2;
}
break;
default:
assert(1); /* Impossible. */
}
/* Check if the raw buffer contains enough bytes to form a character. */
if (incomplete) break;
/*
* Check if the character is in the allowed range:
* #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
* | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
* | [#x10000-#x10FFFF] (32 bit)
*/
if (! (value == 0x09 || value == 0x0A || value == 0x0D
|| (value >= 0x20 && value <= 0x7E)
|| (value == 0x85) || (value >= 0xA0 && value <= 0xD7FF)
|| (value >= 0xE000 && value <= 0xFFFD)
|| (value >= 0x10000 && value <= 0x10FFFF)))
return yaml_parser_set_reader_error(parser,
"control characters are not allowed",
parser->offset, value);
/* Move the raw pointers. */
parser->raw_buffer.pointer += width;
parser->offset += width;
/* Finally put the character into the buffer. */
/* 0000 0000-0000 007F -> 0xxxxxxx */
if (value <= 0x7F) {
*(parser->buffer.last++) = value;
}
/* 0000 0080-0000 07FF -> 110xxxxx 10xxxxxx */
else if (value <= 0x7FF) {
*(parser->buffer.last++) = 0xC0 + (value >> 6);
*(parser->buffer.last++) = 0x80 + (value & 0x3F);
}
/* 0000 0800-0000 FFFF -> 1110xxxx 10xxxxxx 10xxxxxx */
else if (value <= 0xFFFF) {
*(parser->buffer.last++) = 0xE0 + (value >> 12);
*(parser->buffer.last++) = 0x80 + ((value >> 6) & 0x3F);
*(parser->buffer.last++) = 0x80 + (value & 0x3F);
}
/* 0001 0000-0010 FFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
else {
*(parser->buffer.last++) = 0xF0 + (value >> 18);
*(parser->buffer.last++) = 0x80 + ((value >> 12) & 0x3F);
*(parser->buffer.last++) = 0x80 + ((value >> 6) & 0x3F);
*(parser->buffer.last++) = 0x80 + (value & 0x3F);
}
parser->unread ++;
}
/* On EOF, put NUL into the buffer and return. */
if (parser->eof) {
*(parser->buffer.last++) = '\0';
parser->unread ++;
return 1;
}
}
return 1;
}
File diff suppressed because it is too large Load Diff
+141
View File
@@ -0,0 +1,141 @@
#include "libyaml/yaml_private.h"
/*
* Declarations.
*/
static int
yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem);
YAML_DECLARE(int)
yaml_emitter_flush(yaml_emitter_t *emitter);
/*
* Set the writer error and return 0.
*/
static int
yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem)
{
emitter->error = YAML_WRITER_ERROR;
emitter->problem = problem;
return 0;
}
/*
* Flush the output buffer.
*/
YAML_DECLARE(int)
yaml_emitter_flush(yaml_emitter_t *emitter)
{
int low, high;
assert(emitter); /* Non-NULL emitter object is expected. */
assert(emitter->write_handler); /* Write handler must be set. */
assert(emitter->encoding); /* Output encoding must be set. */
emitter->buffer.last = emitter->buffer.pointer;
emitter->buffer.pointer = emitter->buffer.start;
/* Check if the buffer is empty. */
if (emitter->buffer.start == emitter->buffer.last) {
return 1;
}
/* If the output encoding is UTF-8, we don't need to recode the buffer. */
if (emitter->encoding == YAML_UTF8_ENCODING)
{
if (emitter->write_handler(emitter->write_handler_data,
emitter->buffer.start,
emitter->buffer.last - emitter->buffer.start)) {
emitter->buffer.last = emitter->buffer.start;
emitter->buffer.pointer = emitter->buffer.start;
return 1;
}
else {
return yaml_emitter_set_writer_error(emitter, "write error");
}
}
/* Recode the buffer into the raw buffer. */
low = (emitter->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
high = (emitter->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
while (emitter->buffer.pointer != emitter->buffer.last)
{
unsigned char octet;
unsigned int width;
unsigned int value;
size_t k;
/*
* See the "reader.c" code for more details on UTF-8 encoding. Note
* that we assume that the buffer contains a valid UTF-8 sequence.
*/
/* Read the next UTF-8 character. */
octet = emitter->buffer.pointer[0];
width = (octet & 0x80) == 0x00 ? 1 :
(octet & 0xE0) == 0xC0 ? 2 :
(octet & 0xF0) == 0xE0 ? 3 :
(octet & 0xF8) == 0xF0 ? 4 : 0;
value = (octet & 0x80) == 0x00 ? octet & 0x7F :
(octet & 0xE0) == 0xC0 ? octet & 0x1F :
(octet & 0xF0) == 0xE0 ? octet & 0x0F :
(octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
for (k = 1; k < width; k ++) {
octet = emitter->buffer.pointer[k];
value = (value << 6) + (octet & 0x3F);
}
emitter->buffer.pointer += width;
/* Write the character. */
if (value < 0x10000)
{
emitter->raw_buffer.last[high] = value >> 8;
emitter->raw_buffer.last[low] = value & 0xFF;
emitter->raw_buffer.last += 2;
}
else
{
/* Write the character using a surrogate pair (check "reader.c"). */
value -= 0x10000;
emitter->raw_buffer.last[high] = 0xD8 + (value >> 18);
emitter->raw_buffer.last[low] = (value >> 10) & 0xFF;
emitter->raw_buffer.last[high+2] = 0xDC + ((value >> 8) & 0xFF);
emitter->raw_buffer.last[low+2] = value & 0xFF;
emitter->raw_buffer.last += 4;
}
}
/* Write the raw buffer. */
if (emitter->write_handler(emitter->write_handler_data,
emitter->raw_buffer.start,
emitter->raw_buffer.last - emitter->raw_buffer.start)) {
emitter->buffer.last = emitter->buffer.start;
emitter->buffer.pointer = emitter->buffer.start;
emitter->raw_buffer.last = emitter->raw_buffer.start;
emitter->raw_buffer.pointer = emitter->raw_buffer.start;
return 1;
}
else {
return yaml_emitter_set_writer_error(emitter, "write error");
}
}
File diff suppressed because it is too large Load Diff
+646
View File
@@ -0,0 +1,646 @@
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include "libyaml/yaml.h"
#include <assert.h>
#include <limits.h>
#include <string.h>
#define YAML_titleVersion_STRING "0.1.4"
#define YAML_titleVersion_MAJOR 0
#define YAML_titleVersion_MINOR 1
#define YAML_titleVersion_PATCH 4
/*
* Memory management.
*/
YAML_DECLARE(void *)
yaml_malloc(size_t size);
YAML_DECLARE(void *)
yaml_realloc(void *ptr, size_t size);
YAML_DECLARE(void)
yaml_free(void *ptr);
YAML_DECLARE(yaml_char_t *)
yaml_strdup(const yaml_char_t *);
/*
* Reader: Ensure that the buffer contains at least `length` characters.
*/
YAML_DECLARE(int)
yaml_parser_update_buffer(yaml_parser_t *parser, size_t length);
/*
* Scanner: Ensure that the token stack contains at least one token ready.
*/
YAML_DECLARE(int)
yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
/*
* The size of the input raw buffer.
*/
#define INPUT_RAW_BUFFER_SIZE 16384
/*
* The size of the input buffer.
*
* It should be possible to decode the whole raw buffer.
*/
#define INPUT_BUFFER_SIZE (INPUT_RAW_BUFFER_SIZE*3)
/*
* The size of the output buffer.
*/
#define OUTPUT_BUFFER_SIZE 16384
/*
* The size of the output raw buffer.
*
* It should be possible to encode the whole output buffer.
*/
#define OUTPUT_RAW_BUFFER_SIZE (OUTPUT_BUFFER_SIZE*2+2)
/*
* The size of other stacks and queues.
*/
#define INITIAL_STACK_SIZE 16
#define INITIAL_QUEUE_SIZE 16
#define INITIAL_STRING_SIZE 16
/*
* Buffer management.
*/
#define BUFFER_INIT(context,buffer,size) \
(((buffer).start = yaml_malloc(size)) ? \
((buffer).last = (buffer).pointer = (buffer).start, \
(buffer).end = (buffer).start+(size), \
1) : \
((context)->error = YAML_MEMORY_ERROR, \
0))
#define BUFFER_DEL(context,buffer) \
(yaml_free((buffer).start), \
(buffer).start = (buffer).pointer = (buffer).end = 0)
/*
* String management.
*/
typedef struct {
yaml_char_t *start;
yaml_char_t *end;
yaml_char_t *pointer;
} yaml_string_t;
YAML_DECLARE(int)
yaml_string_extend(yaml_char_t **start,
yaml_char_t **pointer, yaml_char_t **end);
YAML_DECLARE(int)
yaml_string_join(
yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end);
#define NULL_STRING { NULL, NULL, NULL }
#define STRING(string,length) { (string), (string)+(length), (string) }
#define STRING_ASSIGN(value,string,length) \
((value).start = (string), \
(value).end = (string)+(length), \
(value).pointer = (string))
#define STRING_INIT(context,string,size) \
(((string).start = yaml_malloc(size)) ? \
((string).pointer = (string).start, \
(string).end = (string).start+(size), \
memset((string).start, 0, (size)), \
1) : \
((context)->error = YAML_MEMORY_ERROR, \
0))
#define STRING_DEL(context,string) \
(yaml_free((string).start), \
(string).start = (string).pointer = (string).end = 0)
#define STRING_EXTEND(context,string) \
(((string).pointer+5 < (string).end) \
|| yaml_string_extend(&(string).start, \
&(string).pointer, &(string).end))
#define CLEAR(context,string) \
((string).pointer = (string).start, \
memset((string).start, 0, (string).end-(string).start))
#define JOIN(context,string_a,string_b) \
((yaml_string_join(&(string_a).start, &(string_a).pointer, \
&(string_a).end, &(string_b).start, \
&(string_b).pointer, &(string_b).end)) ? \
((string_b).pointer = (string_b).start, \
1) : \
((context)->error = YAML_MEMORY_ERROR, \
0))
/*
* String check operations.
*/
/*
* Check the octet at the specified position.
*/
#define CHECK_AT(string,octet,offset) \
((string).pointer[offset] == (yaml_char_t)(octet))
/*
* Check the current octet in the buffer.
*/
#define CHECK(string,octet) CHECK_AT((string),(octet),0)
/*
* Check if the character at the specified position is an alphabetical
* character, a digit, '_', or '-'.
*/
#define IS_ALPHA_AT(string,offset) \
(((string).pointer[offset] >= (yaml_char_t) '0' && \
(string).pointer[offset] <= (yaml_char_t) '9') || \
((string).pointer[offset] >= (yaml_char_t) 'A' && \
(string).pointer[offset] <= (yaml_char_t) 'Z') || \
((string).pointer[offset] >= (yaml_char_t) 'a' && \
(string).pointer[offset] <= (yaml_char_t) 'z') || \
(string).pointer[offset] == '_' || \
(string).pointer[offset] == '-')
#define IS_ALPHA(string) IS_ALPHA_AT((string),0)
/*
* Check if the character at the specified position is a digit.
*/
#define IS_DIGIT_AT(string,offset) \
(((string).pointer[offset] >= (yaml_char_t) '0' && \
(string).pointer[offset] <= (yaml_char_t) '9'))
#define IS_DIGIT(string) IS_DIGIT_AT((string),0)
/*
* Get the value of a digit.
*/
#define AS_DIGIT_AT(string,offset) \
((string).pointer[offset] - (yaml_char_t) '0')
#define AS_DIGIT(string) AS_DIGIT_AT((string),0)
/*
* Check if the character at the specified position is a hex-digit.
*/
#define IS_HEX_AT(string,offset) \
(((string).pointer[offset] >= (yaml_char_t) '0' && \
(string).pointer[offset] <= (yaml_char_t) '9') || \
((string).pointer[offset] >= (yaml_char_t) 'A' && \
(string).pointer[offset] <= (yaml_char_t) 'F') || \
((string).pointer[offset] >= (yaml_char_t) 'a' && \
(string).pointer[offset] <= (yaml_char_t) 'f'))
#define IS_HEX(string) IS_HEX_AT((string),0)
/*
* Get the value of a hex-digit.
*/
#define AS_HEX_AT(string,offset) \
(((string).pointer[offset] >= (yaml_char_t) 'A' && \
(string).pointer[offset] <= (yaml_char_t) 'F') ? \
((string).pointer[offset] - (yaml_char_t) 'A' + 10) : \
((string).pointer[offset] >= (yaml_char_t) 'a' && \
(string).pointer[offset] <= (yaml_char_t) 'f') ? \
((string).pointer[offset] - (yaml_char_t) 'a' + 10) : \
((string).pointer[offset] - (yaml_char_t) '0'))
#define AS_HEX(string) AS_HEX_AT((string),0)
/*
* Check if the character is ASCII.
*/
#define IS_ASCII_AT(string,offset) \
((string).pointer[offset] <= (yaml_char_t) '\x7F')
#define IS_ASCII(string) IS_ASCII_AT((string),0)
/*
* Check if the character can be printed unescaped.
*/
#define IS_PRINTABLE_AT(string,offset) \
(((string).pointer[offset] == 0x0A) /* . == #x0A */ \
|| ((string).pointer[offset] >= 0x20 /* #x20 <= . <= #x7E */ \
&& (string).pointer[offset] <= 0x7E) \
|| ((string).pointer[offset] == 0xC2 /* #0xA0 <= . <= #xD7FF */ \
&& (string).pointer[offset+1] >= 0xA0) \
|| ((string).pointer[offset] > 0xC2 \
&& (string).pointer[offset] < 0xED) \
|| ((string).pointer[offset] == 0xED \
&& (string).pointer[offset+1] < 0xA0) \
|| ((string).pointer[offset] == 0xEE) \
|| ((string).pointer[offset] == 0xEF /* #xE000 <= . <= #xFFFD */ \
&& !((string).pointer[offset+1] == 0xBB /* && . != #xFEFF */ \
&& (string).pointer[offset+2] == 0xBF) \
&& !((string).pointer[offset+1] == 0xBF \
&& ((string).pointer[offset+2] == 0xBE \
|| (string).pointer[offset+2] == 0xBF))))
#define IS_PRINTABLE(string) IS_PRINTABLE_AT((string),0)
/*
* Check if the character at the specified position is NUL.
*/
#define IS_Z_AT(string,offset) CHECK_AT((string),'\0',(offset))
#define IS_Z(string) IS_Z_AT((string),0)
/*
* Check if the character at the specified position is BOM.
*/
#define IS_BOM_AT(string,offset) \
(CHECK_AT((string),'\xEF',(offset)) \
&& CHECK_AT((string),'\xBB',(offset)+1) \
&& CHECK_AT((string),'\xBF',(offset)+2)) /* BOM (#xFEFF) */
#define IS_BOM(string) IS_BOM_AT(string,0)
/*
* Check if the character at the specified position is space.
*/
#define IS_SPACE_AT(string,offset) CHECK_AT((string),' ',(offset))
#define IS_SPACE(string) IS_SPACE_AT((string),0)
/*
* Check if the character at the specified position is tab.
*/
#define IS_TAB_AT(string,offset) CHECK_AT((string),'\t',(offset))
#define IS_TAB(string) IS_TAB_AT((string),0)
/*
* Check if the character at the specified position is blank (space or tab).
*/
#define IS_BLANK_AT(string,offset) \
(IS_SPACE_AT((string),(offset)) || IS_TAB_AT((string),(offset)))
#define IS_BLANK(string) IS_BLANK_AT((string),0)
/*
* Check if the character at the specified position is a line break.
*/
#define IS_BREAK_AT(string,offset) \
(CHECK_AT((string),'\r',(offset)) /* CR (#xD)*/ \
|| CHECK_AT((string),'\n',(offset)) /* LF (#xA) */ \
|| (CHECK_AT((string),'\xC2',(offset)) \
&& CHECK_AT((string),'\x85',(offset)+1)) /* NEL (#x85) */ \
|| (CHECK_AT((string),'\xE2',(offset)) \
&& CHECK_AT((string),'\x80',(offset)+1) \
&& CHECK_AT((string),'\xA8',(offset)+2)) /* LS (#x2028) */ \
|| (CHECK_AT((string),'\xE2',(offset)) \
&& CHECK_AT((string),'\x80',(offset)+1) \
&& CHECK_AT((string),'\xA9',(offset)+2))) /* PS (#x2029) */
#define IS_BREAK(string) IS_BREAK_AT((string),0)
#define IS_CRLF_AT(string,offset) \
(CHECK_AT((string),'\r',(offset)) && CHECK_AT((string),'\n',(offset)+1))
#define IS_CRLF(string) IS_CRLF_AT((string),0)
/*
* Check if the character is a line break or NUL.
*/
#define IS_BREAKZ_AT(string,offset) \
(IS_BREAK_AT((string),(offset)) || IS_Z_AT((string),(offset)))
#define IS_BREAKZ(string) IS_BREAKZ_AT((string),0)
/*
* Check if the character is a line break, space, or NUL.
*/
#define IS_SPACEZ_AT(string,offset) \
(IS_SPACE_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset)))
#define IS_SPACEZ(string) IS_SPACEZ_AT((string),0)
/*
* Check if the character is a line break, space, tab, or NUL.
*/
#define IS_BLANKZ_AT(string,offset) \
(IS_BLANK_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset)))
#define IS_BLANKZ(string) IS_BLANKZ_AT((string),0)
/*
* Determine the width of the character.
*/
#define WIDTH_AT(string,offset) \
(((string).pointer[offset] & 0x80) == 0x00 ? 1 : \
((string).pointer[offset] & 0xE0) == 0xC0 ? 2 : \
((string).pointer[offset] & 0xF0) == 0xE0 ? 3 : \
((string).pointer[offset] & 0xF8) == 0xF0 ? 4 : 0)
#define WIDTH(string) WIDTH_AT((string),0)
/*
* Move the string pointer to the next character.
*/
#define MOVE(string) ((string).pointer += WIDTH((string)))
/*
* Copy a character and move the pointers of both strings.
*/
#define COPY(string_a,string_b) \
((*(string_b).pointer & 0x80) == 0x00 ? \
(*((string_a).pointer++) = *((string_b).pointer++)) : \
(*(string_b).pointer & 0xE0) == 0xC0 ? \
(*((string_a).pointer++) = *((string_b).pointer++), \
*((string_a).pointer++) = *((string_b).pointer++)) : \
(*(string_b).pointer & 0xF0) == 0xE0 ? \
(*((string_a).pointer++) = *((string_b).pointer++), \
*((string_a).pointer++) = *((string_b).pointer++), \
*((string_a).pointer++) = *((string_b).pointer++)) : \
(*(string_b).pointer & 0xF8) == 0xF0 ? \
(*((string_a).pointer++) = *((string_b).pointer++), \
*((string_a).pointer++) = *((string_b).pointer++), \
*((string_a).pointer++) = *((string_b).pointer++), \
*((string_a).pointer++) = *((string_b).pointer++)) : 0)
/*
* Stack and queue management.
*/
YAML_DECLARE(int)
yaml_stack_extend(void **start, void **top, void **end);
YAML_DECLARE(int)
yaml_queue_extend(void **start, void **head, void **tail, void **end);
#define STACK_INIT(context,stack,size) \
(((stack).start = yaml_malloc((size)*sizeof(*(stack).start))) ? \
((stack).top = (stack).start, \
(stack).end = (stack).start+(size), \
1) : \
((context)->error = YAML_MEMORY_ERROR, \
0))
#define STACK_DEL(context,stack) \
(yaml_free((stack).start), \
(stack).start = (stack).top = (stack).end = 0)
#define STACK_EMPTY(context,stack) \
((stack).start == (stack).top)
#define PUSH(context,stack,value) \
(((stack).top != (stack).end \
|| yaml_stack_extend((void **)&(stack).start, \
(void **)&(stack).top, (void **)&(stack).end)) ? \
(*((stack).top++) = value, \
1) : \
((context)->error = YAML_MEMORY_ERROR, \
0))
#define POP(context,stack) \
(*(--(stack).top))
#define QUEUE_INIT(context,queue,size) \
(((queue).start = yaml_malloc((size)*sizeof(*(queue).start))) ? \
((queue).head = (queue).tail = (queue).start, \
(queue).end = (queue).start+(size), \
1) : \
((context)->error = YAML_MEMORY_ERROR, \
0))
#define QUEUE_DEL(context,queue) \
(yaml_free((queue).start), \
(queue).start = (queue).head = (queue).tail = (queue).end = 0)
#define QUEUE_EMPTY(context,queue) \
((queue).head == (queue).tail)
#define ENQUEUE(context,queue,value) \
(((queue).tail != (queue).end \
|| yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \
(void **)&(queue).tail, (void **)&(queue).end)) ? \
(*((queue).tail++) = value, \
1) : \
((context)->error = YAML_MEMORY_ERROR, \
0))
#define DEQUEUE(context,queue) \
(*((queue).head++))
#define QUEUE_INSERT(context,queue,index,value) \
(((queue).tail != (queue).end \
|| yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \
(void **)&(queue).tail, (void **)&(queue).end)) ? \
(memmove((queue).head+(index)+1,(queue).head+(index), \
((queue).tail-(queue).head-(index))*sizeof(*(queue).start)), \
*((queue).head+(index)) = value, \
(queue).tail++, \
1) : \
((context)->error = YAML_MEMORY_ERROR, \
0))
/*
* Token initializers.
*/
#define TOKEN_INIT(token,token_type,token_start_mark,token_end_mark) \
(memset(&(token), 0, sizeof(yaml_token_t)), \
(token).type = (token_type), \
(token).start_mark = (token_start_mark), \
(token).end_mark = (token_end_mark))
#define STREAM_START_TOKEN_INIT(token,token_encoding,start_mark,end_mark) \
(TOKEN_INIT((token),YAML_STREAM_START_TOKEN,(start_mark),(end_mark)), \
(token).data.stream_start.encoding = (token_encoding))
#define STREAM_END_TOKEN_INIT(token,start_mark,end_mark) \
(TOKEN_INIT((token),YAML_STREAM_END_TOKEN,(start_mark),(end_mark)))
#define ALIAS_TOKEN_INIT(token,token_value,start_mark,end_mark) \
(TOKEN_INIT((token),YAML_ALIAS_TOKEN,(start_mark),(end_mark)), \
(token).data.alias.value = (token_value))
#define ANCHOR_TOKEN_INIT(token,token_value,start_mark,end_mark) \
(TOKEN_INIT((token),YAML_ANCHOR_TOKEN,(start_mark),(end_mark)), \
(token).data.anchor.value = (token_value))
#define TAG_TOKEN_INIT(token,token_handle,token_suffix,start_mark,end_mark) \
(TOKEN_INIT((token),YAML_TAG_TOKEN,(start_mark),(end_mark)), \
(token).data.tag.handle = (token_handle), \
(token).data.tag.suffix = (token_suffix))
#define SCALAR_TOKEN_INIT(token,token_value,token_length,token_style,start_mark,end_mark) \
(TOKEN_INIT((token),YAML_SCALAR_TOKEN,(start_mark),(end_mark)), \
(token).data.scalar.value = (token_value), \
(token).data.scalar.length = (token_length), \
(token).data.scalar.style = (token_style))
#define titleVersion_DIRECTIVE_TOKEN_INIT(token,token_major,token_minor,start_mark,end_mark) \
(TOKEN_INIT((token),YAML_titleVersion_DIRECTIVE_TOKEN,(start_mark),(end_mark)), \
(token).data.titleVersion_directive.major = (token_major), \
(token).data.titleVersion_directive.minor = (token_minor))
#define TAG_DIRECTIVE_TOKEN_INIT(token,token_handle,token_prefix,start_mark,end_mark) \
(TOKEN_INIT((token),YAML_TAG_DIRECTIVE_TOKEN,(start_mark),(end_mark)), \
(token).data.tag_directive.handle = (token_handle), \
(token).data.tag_directive.prefix = (token_prefix))
/*
* Event initializers.
*/
#define EVENT_INIT(event,event_type,event_start_mark,event_end_mark) \
(memset(&(event), 0, sizeof(yaml_event_t)), \
(event).type = (event_type), \
(event).start_mark = (event_start_mark), \
(event).end_mark = (event_end_mark))
#define STREAM_START_EVENT_INIT(event,event_encoding,start_mark,end_mark) \
(EVENT_INIT((event),YAML_STREAM_START_EVENT,(start_mark),(end_mark)), \
(event).data.stream_start.encoding = (event_encoding))
#define STREAM_END_EVENT_INIT(event,start_mark,end_mark) \
(EVENT_INIT((event),YAML_STREAM_END_EVENT,(start_mark),(end_mark)))
#define DOCUMENT_START_EVENT_INIT(event,event_titleVersion_directive, \
event_tag_directives_start,event_tag_directives_end,event_implicit,start_mark,end_mark) \
(EVENT_INIT((event),YAML_DOCUMENT_START_EVENT,(start_mark),(end_mark)), \
(event).data.document_start.titleVersion_directive = (event_titleVersion_directive), \
(event).data.document_start.tag_directives.start = (event_tag_directives_start), \
(event).data.document_start.tag_directives.end = (event_tag_directives_end), \
(event).data.document_start.implicit = (event_implicit))
#define DOCUMENT_END_EVENT_INIT(event,event_implicit,start_mark,end_mark) \
(EVENT_INIT((event),YAML_DOCUMENT_END_EVENT,(start_mark),(end_mark)), \
(event).data.document_end.implicit = (event_implicit))
#define ALIAS_EVENT_INIT(event,event_anchor,start_mark,end_mark) \
(EVENT_INIT((event),YAML_ALIAS_EVENT,(start_mark),(end_mark)), \
(event).data.alias.anchor = (event_anchor))
#define SCALAR_EVENT_INIT(event,event_anchor,event_tag,event_value,event_length, \
event_plain_implicit, event_quoted_implicit,event_style,start_mark,end_mark) \
(EVENT_INIT((event),YAML_SCALAR_EVENT,(start_mark),(end_mark)), \
(event).data.scalar.anchor = (event_anchor), \
(event).data.scalar.tag = (event_tag), \
(event).data.scalar.value = (event_value), \
(event).data.scalar.length = (event_length), \
(event).data.scalar.plain_implicit = (event_plain_implicit), \
(event).data.scalar.quoted_implicit = (event_quoted_implicit), \
(event).data.scalar.style = (event_style))
#define SEQUENCE_START_EVENT_INIT(event,event_anchor,event_tag, \
event_implicit,event_style,start_mark,end_mark) \
(EVENT_INIT((event),YAML_SEQUENCE_START_EVENT,(start_mark),(end_mark)), \
(event).data.sequence_start.anchor = (event_anchor), \
(event).data.sequence_start.tag = (event_tag), \
(event).data.sequence_start.implicit = (event_implicit), \
(event).data.sequence_start.style = (event_style))
#define SEQUENCE_END_EVENT_INIT(event,start_mark,end_mark) \
(EVENT_INIT((event),YAML_SEQUENCE_END_EVENT,(start_mark),(end_mark)))
#define MAPPING_START_EVENT_INIT(event,event_anchor,event_tag, \
event_implicit,event_style,start_mark,end_mark) \
(EVENT_INIT((event),YAML_MAPPING_START_EVENT,(start_mark),(end_mark)), \
(event).data.mapping_start.anchor = (event_anchor), \
(event).data.mapping_start.tag = (event_tag), \
(event).data.mapping_start.implicit = (event_implicit), \
(event).data.mapping_start.style = (event_style))
#define MAPPING_END_EVENT_INIT(event,start_mark,end_mark) \
(EVENT_INIT((event),YAML_MAPPING_END_EVENT,(start_mark),(end_mark)))
/*
* Document initializer.
*/
#define DOCUMENT_INIT(document,document_nodes_start,document_nodes_end, \
document_titleVersion_directive,document_tag_directives_start, \
document_tag_directives_end,document_start_implicit, \
document_end_implicit,document_start_mark,document_end_mark) \
(memset(&(document), 0, sizeof(yaml_document_t)), \
(document).nodes.start = (document_nodes_start), \
(document).nodes.end = (document_nodes_end), \
(document).nodes.top = (document_nodes_start), \
(document).titleVersion_directive = (document_titleVersion_directive), \
(document).tag_directives.start = (document_tag_directives_start), \
(document).tag_directives.end = (document_tag_directives_end), \
(document).start_implicit = (document_start_implicit), \
(document).end_implicit = (document_end_implicit), \
(document).start_mark = (document_start_mark), \
(document).end_mark = (document_end_mark))
/*
* Node initializers.
*/
#define NODE_INIT(node,node_type,node_tag,node_start_mark,node_end_mark) \
(memset(&(node), 0, sizeof(yaml_node_t)), \
(node).type = (node_type), \
(node).tag = (node_tag), \
(node).start_mark = (node_start_mark), \
(node).end_mark = (node_end_mark))
#define SCALAR_NODE_INIT(node,node_tag,node_value,node_length, \
node_style,start_mark,end_mark) \
(NODE_INIT((node),YAML_SCALAR_NODE,(node_tag),(start_mark),(end_mark)), \
(node).data.scalar.value = (node_value), \
(node).data.scalar.length = (node_length), \
(node).data.scalar.style = (node_style))
#define SEQUENCE_NODE_INIT(node,node_tag,node_items_start,node_items_end, \
node_style,start_mark,end_mark) \
(NODE_INIT((node),YAML_SEQUENCE_NODE,(node_tag),(start_mark),(end_mark)), \
(node).data.sequence.items.start = (node_items_start), \
(node).data.sequence.items.end = (node_items_end), \
(node).data.sequence.items.top = (node_items_start), \
(node).data.sequence.style = (node_style))
#define MAPPING_NODE_INIT(node,node_tag,node_pairs_start,node_pairs_end, \
node_style,start_mark,end_mark) \
(NODE_INIT((node),YAML_MAPPING_NODE,(node_tag),(start_mark),(end_mark)), \
(node).data.mapping.pairs.start = (node_pairs_start), \
(node).data.mapping.pairs.end = (node_pairs_end), \
(node).data.mapping.pairs.top = (node_pairs_start), \
(node).data.mapping.style = (node_style))
File diff suppressed because it is too large Load Diff
+202
View File
@@ -0,0 +1,202 @@
/**
* \file aes.h
*
* \brief AES block cipher
*
* Copyright (C) 2006-2013, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_AES_H
#define POLARSSL_AES_H
#include "polarssl/config.h"
#include <string.h>
#ifdef _MSC_VER
#include <basetsd.h>
typedef UINT32 uint32_t;
#else
#include <inttypes.h>
#endif
#define AES_ENCRYPT 1
#define AES_DECRYPT 0
#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
#if !defined(POLARSSL_AES_ALT)
// Regular implementation
//
/**
* \brief AES context structure
*/
typedef struct
{
int nr; /*!< number of rounds */
uint32_t *rk; /*!< AES round keys */
uint32_t buf[68]; /*!< unaligned data */
}
aes_context;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief AES key schedule (encryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keysize must be 128, 192 or 256
*
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
*/
int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize );
/**
* \brief AES key schedule (decryption)
*
* \param ctx AES context to be initialized
* \param key decryption key
* \param keysize must be 128, 192 or 256
*
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
*/
int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize );
/**
* \brief AES-ECB block encryption/decryption
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if successful
*/
int aes_crypt_ecb( aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] );
/**
* \brief AES-CBC buffer encryption/decryption
* Length should be a multiple of the block
* size (16 bytes)
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH
*/
int aes_crypt_cbc( aes_context *ctx,
int mode,
uint64_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief AES-CFB128 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
*
* both
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv_off offset in IV (updated after use)
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int aes_crypt_cfb128( aes_context *ctx,
int mode,
uint64_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief AES-CTR buffer encryption/decryption
*
* Warning: You have to keep the maximum use of your counter in mind!
*
* Note: Due to the nature of CTR you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
*
* \param length The length of the data
* \param nc_off The offset in the current stream_block (for resuming
* within current cipher stream). The offset pointer to
* should be 0 at the start of a stream.
* \param nonce_counter The 128-bit nonce and counter.
* \param stream_block The saved stream-block for resuming. Is overwritten
* by the function.
* \param input The input data stream
* \param output The output data stream
*
* \return 0 if successful
*/
int aes_crypt_ctr( aes_context *ctx,
uint64_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output );
#ifdef __cplusplus
}
#endif
#else /* POLARSSL_AES_ALT */
#include "polarssl/aes_alt.h"
#endif /* POLARSSL_AES_ALT */
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int aes_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* aes.h */
+269
View File
@@ -0,0 +1,269 @@
/*
* RFC 1521 base64 encoding/decoding
*
* Copyright (C) 2006-2010, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "polarssl/config.h"
#if defined(POLARSSL_BASE64_C)
#include "polarssl/base64.h"
#ifdef _MSC_VER
#include <basetsd.h>
typedef UINT32 uint32_t;
#else
#include <inttypes.h>
#endif
static const unsigned char base64_enc_map[64] =
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '+', '/'
};
static const unsigned char base64_dec_map[128] =
{
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 127, 127, 127, 127, 127
};
/*
* Encode a buffer into base64 format
*/
int base64_encode( unsigned char *dst, size_t *dlen,
const unsigned char *src, size_t slen )
{
size_t i, n;
int C1, C2, C3;
unsigned char *p;
if( slen == 0 )
return( 0 );
n = (slen << 3) / 6;
switch( (slen << 3) - (n * 6) )
{
case 2: n += 3; break;
case 4: n += 2; break;
default: break;
}
if( *dlen < n + 1 )
{
*dlen = n + 1;
return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
}
n = (slen / 3) * 3;
for( i = 0, p = dst; i < n; i += 3 )
{
C1 = *src++;
C2 = *src++;
C3 = *src++;
*p++ = base64_enc_map[(C1 >> 2) & 0x3F];
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
*p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
*p++ = base64_enc_map[C3 & 0x3F];
}
if( i < slen )
{
C1 = *src++;
C2 = ((i + 1) < slen) ? *src++ : 0;
*p++ = base64_enc_map[(C1 >> 2) & 0x3F];
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
if( (i + 1) < slen )
*p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
else *p++ = '=';
*p++ = '=';
}
*dlen = p - dst;
*p = 0;
return( 0 );
}
/*
* Decode a base64-formatted buffer
*/
int base64_decode( unsigned char *dst, size_t *dlen,
const unsigned char *src, size_t slen )
{
size_t i, n;
uint32_t j, x;
unsigned char *p;
for( i = j = n = 0; i < slen; i++ )
{
if( ( slen - i ) >= 2 &&
src[i] == '\r' && src[i + 1] == '\n' )
continue;
if( src[i] == '\n' )
continue;
if( src[i] == '=' && ++j > 2 ){
printf("err 0 char[%lu] = '%c' (0x%x)\n",i,src[i],src[i]);
return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
}
if( src[i] > 127 || base64_dec_map[src[i]] == 127 ){
printf("err 1 char[%lu] = '%c' (0x%x)\n",i,src[i],src[i]);
return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
}
if( base64_dec_map[src[i]] < 64 && j != 0 ){
printf("err 2 char[%lu] = '%c' (0x%x)\n",i,src[i],src[i]);
return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
}
n++;
}
if( n == 0 )
return( 0 );
n = ((n * 6) + 7) >> 3;
if( (*dlen+4) < n )
{
*dlen = n;
return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
}
for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
{
if( *src == '\r' || *src == '\n' )
continue;
j -= ( base64_dec_map[*src] == 64 );
x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
if( ++n == 4 )
{
n = 0;
if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
if( j > 2 ) *p++ = (unsigned char)( x );
}
}
*dlen = p - dst;
return( 0 );
}
#if defined(POLARSSL_SELF_TEST)
#include <string.h>
#include <stdio.h>
static const unsigned char base64_test_dec[64] =
{
0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
};
static const unsigned char base64_test_enc[] =
"JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
"swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
/*
* Checkup routine
*/
int base64_self_test( int verbose )
{
size_t len;
const unsigned char *src;
unsigned char buffer[128];
if( verbose != 0 )
printf( " Base64 encoding test: " );
len = sizeof( buffer );
src = base64_test_dec;
if( base64_encode( buffer, &len, src, 64 ) != 0 ||
memcmp( base64_test_enc, buffer, 88 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n Base64 decoding test: " );
len = sizeof( buffer );
src = base64_test_enc;
if( base64_decode( buffer, &len, src, 88 ) != 0 ||
memcmp( base64_test_dec, buffer, 64 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n\n" );
return( 0 );
}
#endif
#endif
+88
View File
@@ -0,0 +1,88 @@
/**
* \file base64.h
*
* \brief RFC 1521 base64 encoding/decoding
*
* Copyright (C) 2006-2010, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_BASE64_H
#define POLARSSL_BASE64_H
#include <string.h>
#include <stdio.h>
#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */
#define POLARSSL_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Encode a buffer into base64 format
*
* \param dst destination buffer
* \param dlen size of the buffer
* \param src source buffer
* \param slen amount of data to be encoded
*
* \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL.
* *dlen is always updated to reflect the amount
* of data that has (or would have) been written.
*
* \note Call this function with *dlen = 0 to obtain the
* required buffer size in *dlen
*/
int base64_encode( unsigned char *dst, size_t *dlen,
const unsigned char *src, size_t slen );
/**
* \brief Decode a base64-formatted buffer
*
* \param dst destination buffer
* \param dlen size of the buffer
* \param src source buffer
* \param slen amount of data to be decoded
*
* \return 0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or
* POLARSSL_ERR_BASE64_INVALID_CHARACTER if the input data is
* not correct. *dlen is always updated to reflect the amount
* of data that has (or would have) been written.
*
* \note Call this function with *dlen = 0 to obtain the
* required buffer size in *dlen
*/
int base64_decode( unsigned char *dst, size_t *dlen,
const unsigned char *src, size_t slen );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int base64_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* base64.h */
File diff suppressed because it is too large Load Diff
+685
View File
@@ -0,0 +1,685 @@
/**
* \file bignum.h
*
* \brief Multi-precision integer library
*
* Copyright (C) 2006-2013, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_BIGNUM_H
#define POLARSSL_BIGNUM_H
#include <stdio.h>
#include <string.h>
#include "polarssl/config.h"
#ifdef _MSC_VER
#include <basetsd.h>
#if (_MSC_VER <= 1200)
typedef signed short int16_t;
typedef unsigned short uint16_t;
#else
typedef INT16 int16_t;
typedef UINT16 uint16_t;
#endif
typedef INT32 int32_t;
typedef INT64 int64_t;
typedef UINT32 uint32_t;
typedef UINT64 uint64_t;
#else
#include <inttypes.h>
#endif
#define POLARSSL_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */
#define POLARSSL_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */
#define POLARSSL_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */
#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */
#define POLARSSL_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */
#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */
#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */
#define POLARSSL_ERR_MPI_MALLOC_FAILED -0x0010 /**< Memory allocation failed. */
#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup
/*
* Maximum size MPIs are allowed to grow to in number of limbs.
*/
#define POLARSSL_MPI_MAX_LIMBS 10000
#if !defined(POLARSSL_CONFIG_OPTIONS)
/*
* Maximum window size used for modular exponentiation. Default: 6
* Minimum value: 1. Maximum value: 6.
*
* Result is an array of ( 2 << POLARSSL_MPI_WINDOW_SIZE ) MPIs used
* for the sliding window calculation. (So 64 by default)
*
* Reduction in size, reduces speed.
*/
#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */
/*
* Maximum size of MPIs allowed in bits and bytes for user-MPIs.
* ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits )
*
* Note: Calculations can results temporarily in larger MPIs. So the number
* of limbs required (POLARSSL_MPI_MAX_LIMBS) is higher.
*/
#define POLARSSL_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */
#endif /* !POLARSSL_CONFIG_OPTIONS */
#define POLARSSL_MPI_MAX_BITS ( 8 * POLARSSL_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */
/*
* When reading from files with mpi_read_file() and writing to files with
* mpi_write_file() the buffer should have space
* for a (short) label, the MPI (in the provided radix), the newline
* characters and the '\0'.
*
* By default we assume at least a 10 char label, a minimum radix of 10
* (decimal) and a maximum of 4096 bit numbers (1234 decimal chars).
* Autosized at compile time for at least a 10 char label, a minimum radix
* of 10 (decimal) for a number of POLARSSL_MPI_MAX_BITS size.
*
* This used to be statically sized to 1250 for a maximum of 4096 bit
* numbers (1234 decimal chars).
*
* Calculate using the formula:
* POLARSSL_MPI_RW_BUFFER_SIZE = ceil(POLARSSL_MPI_MAX_BITS / ln(10) * ln(2)) +
* LabelSize + 6
*/
#define POLARSSL_MPI_MAX_BITS_SCALE100 ( 100 * POLARSSL_MPI_MAX_BITS )
#define LN_2_DIV_LN_10_SCALE100 332
#define POLARSSL_MPI_RW_BUFFER_SIZE ( ((POLARSSL_MPI_MAX_BITS_SCALE100 + LN_2_DIV_LN_10_SCALE100 - 1) / LN_2_DIV_LN_10_SCALE100) + 10 + 6 )
/*
* Define the base integer type, architecture-wise
*/
#if defined(POLARSSL_HAVE_INT8)
typedef signed char t_sint;
typedef unsigned char t_uint;
typedef uint16_t t_udbl;
#define POLARSSL_HAVE_UDBL
#else
#if defined(POLARSSL_HAVE_INT16)
typedef int16_t t_sint;
typedef uint16_t t_uint;
typedef uint32_t t_udbl;
#define POLARSSL_HAVE_UDBL
#else
#if ( defined(_MSC_VER) && defined(_M_AMD64) )
typedef int64_t t_sint;
typedef uint64_t t_uint;
#else
#if ( defined(__GNUC__) && ( \
defined(__amd64__) || defined(__x86_64__) || \
defined(__ppc64__) || defined(__powerpc64__) || \
defined(__ia64__) || defined(__alpha__) || \
(defined(__sparc__) && defined(__arch64__)) || \
defined(__s390x__) ) )
typedef int64_t t_sint;
typedef uint64_t t_uint;
typedef unsigned int t_udbl __attribute__((mode(TI)));
#define POLARSSL_HAVE_UDBL
#else
typedef int32_t t_sint;
typedef uint32_t t_uint;
#if ( defined(_MSC_VER) && defined(_M_IX86) )
typedef uint64_t t_udbl;
#define POLARSSL_HAVE_UDBL
#else
#if defined( POLARSSL_HAVE_LONGLONG )
typedef unsigned long long t_udbl;
#define POLARSSL_HAVE_UDBL
#endif
#endif
#endif
#endif
#endif /* POLARSSL_HAVE_INT16 */
#endif /* POLARSSL_HAVE_INT8 */
/**
* \brief MPI structure
*/
typedef struct
{
int s; /*!< integer sign */
size_t n; /*!< total # of limbs */
t_uint *p; /*!< pointer to limbs */
}
mpi;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Initialize one MPI
*
* \param X One MPI to initialize.
*/
void mpi_init( mpi *X );
/**
* \brief Unallocate one MPI
*
* \param X One MPI to unallocate.
*/
void mpi_free( mpi *X );
/**
* \brief Enlarge to the specified number of limbs
*
* \param X MPI to grow
* \param nblimbs The target number of limbs
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_grow( mpi *X, size_t nblimbs );
/**
* \brief Copy the contents of Y into X
*
* \param X Destination MPI
* \param Y Source MPI
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_copy( mpi *X, const mpi *Y );
/**
* \brief Swap the contents of X and Y
*
* \param X First MPI value
* \param Y Second MPI value
*/
void mpi_swap( mpi *X, mpi *Y );
/**
* \brief Set value from integer
*
* \param X MPI to set
* \param z Value to use
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_lset( mpi *X, t_sint z );
/**
* \brief Get a specific bit from X
*
* \param X MPI to use
* \param pos Zero-based index of the bit in X
*
* \return Either a 0 or a 1
*/
int mpi_get_bit( const mpi *X, size_t pos );
/**
* \brief Set a bit of X to a specific value of 0 or 1
*
* \note Will grow X if necessary to set a bit to 1 in a not yet
* existing limb. Will not grow if bit should be set to 0
*
* \param X MPI to use
* \param pos Zero-based index of the bit in X
* \param val The value to set the bit to (0 or 1)
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
* POLARSSL_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1
*/
int mpi_set_bit( mpi *X, size_t pos, unsigned char val );
/**
* \brief Return the number of zero-bits before the least significant
* '1' bit
*
* Note: Thus also the zero-based index of the least significant '1' bit
*
* \param X MPI to use
*/
size_t mpi_lsb( const mpi *X );
/**
* \brief Return the number of bits up to and including the most
* significant '1' bit'
*
* Note: Thus also the one-based index of the most significant '1' bit
*
* \param X MPI to use
*/
size_t mpi_msb( const mpi *X );
/**
* \brief Return the total size in bytes
*
* \param X MPI to use
*/
size_t mpi_size( const mpi *X );
/**
* \brief Import from an ASCII string
*
* \param X Destination MPI
* \param radix Input numeric base
* \param s Null-terminated string buffer
*
* \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code
*/
int mpi_read_string( mpi *X, int radix, const char *s );
/**
* \brief Export into an ASCII string
*
* \param X Source MPI
* \param radix Output numeric base
* \param s String buffer
* \param slen String buffer size
*
* \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code.
* *slen is always updated to reflect the amount
* of data that has (or would have) been written.
*
* \note Call this function with *slen = 0 to obtain the
* minimum required buffer size in *slen.
*/
int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen );
#if defined(POLARSSL_FS_IO)
/**
* \brief Read X from an opened file
*
* \param X Destination MPI
* \param radix Input numeric base
* \param fin Input file handle
*
* \return 0 if successful, POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if
* the file read buffer is too small or a
* POLARSSL_ERR_MPI_XXX error code
*/
int mpi_read_file( mpi *X, int radix, FILE *fin );
/**
* \brief Write X into an opened file, or stdout if fout is NULL
*
* \param p Prefix, can be NULL
* \param X Source MPI
* \param radix Output numeric base
* \param fout Output file handle (can be NULL)
*
* \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code
*
* \note Set fout == NULL to print X on the console.
*/
int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout );
#endif /* POLARSSL_FS_IO */
/**
* \brief Import X from unsigned binary data, big endian
*
* \param X Destination MPI
* \param buf Input buffer
* \param buflen Input buffer size
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen );
/**
* \brief Export X into unsigned binary data, big endian
*
* \param X Source MPI
* \param buf Output buffer
* \param buflen Output buffer size
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
*/
int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen );
/**
* \brief Left-shift: X <<= count
*
* \param X MPI to shift
* \param count Amount to shift
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_shift_l( mpi *X, size_t count );
/**
* \brief Right-shift: X >>= count
*
* \param X MPI to shift
* \param count Amount to shift
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_shift_r( mpi *X, size_t count );
/**
* \brief Compare unsigned values
*
* \param X Left-hand MPI
* \param Y Right-hand MPI
*
* \return 1 if |X| is greater than |Y|,
* -1 if |X| is lesser than |Y| or
* 0 if |X| is equal to |Y|
*/
int mpi_cmp_abs( const mpi *X, const mpi *Y );
/**
* \brief Compare signed values
*
* \param X Left-hand MPI
* \param Y Right-hand MPI
*
* \return 1 if X is greater than Y,
* -1 if X is lesser than Y or
* 0 if X is equal to Y
*/
int mpi_cmp_mpi( const mpi *X, const mpi *Y );
/**
* \brief Compare signed values
*
* \param X Left-hand MPI
* \param z The integer value to compare to
*
* \return 1 if X is greater than z,
* -1 if X is lesser than z or
* 0 if X is equal to z
*/
int mpi_cmp_int( const mpi *X, t_sint z );
/**
* \brief Unsigned addition: X = |A| + |B|
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_add_abs( mpi *X, const mpi *A, const mpi *B );
/**
* \brief Unsigned substraction: X = |A| - |B|
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A
*/
int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B );
/**
* \brief Signed addition: X = A + B
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B );
/**
* \brief Signed substraction: X = A - B
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B );
/**
* \brief Signed addition: X = A + b
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param b The integer value to add
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_add_int( mpi *X, const mpi *A, t_sint b );
/**
* \brief Signed substraction: X = A - b
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param b The integer value to subtract
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_sub_int( mpi *X, const mpi *A, t_sint b );
/**
* \brief Baseline multiplication: X = A * B
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B );
/**
* \brief Baseline multiplication: X = A * b
* Note: b is an unsigned integer type, thus
* Negative values of b are ignored.
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param b The integer value to multiply with
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_mul_int( mpi *X, const mpi *A, t_sint b );
/**
* \brief Division by mpi: A = Q * B + R
*
* \param Q Destination MPI for the quotient
* \param R Destination MPI for the rest value
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
* POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0
*
* \note Either Q or R can be NULL.
*/
int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B );
/**
* \brief Division by int: A = Q * b + R
*
* \param Q Destination MPI for the quotient
* \param R Destination MPI for the rest value
* \param A Left-hand MPI
* \param b Integer to divide by
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
* POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
*
* \note Either Q or R can be NULL.
*/
int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b );
/**
* \brief Modulo: R = A mod B
*
* \param R Destination MPI for the rest value
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
* POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0,
* POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0
*/
int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B );
/**
* \brief Modulo: r = A mod b
*
* \param r Destination t_uint
* \param A Left-hand MPI
* \param b Integer to divide by
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
* POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0,
* POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0
*/
int mpi_mod_int( t_uint *r, const mpi *A, t_sint b );
/**
* \brief Sliding-window exponentiation: X = A^E mod N
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param E Exponent MPI
* \param N Modular MPI
* \param _RR Speed-up MPI used for recalculations
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
* POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even or if
* E is negative
*
* \note _RR is used to avoid re-computing R*R mod N across
* multiple calls, which speeds up things a bit. It can
* be set to NULL if the extra performance is unneeded.
*/
int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR );
/**
* \brief Fill an MPI X with size bytes of random
*
* \param X Destination MPI
* \param size Size in bytes
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_fill_random( mpi *X, size_t size,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Greatest common divisor: G = gcd(A, B)
*
* \param G Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
*/
int mpi_gcd( mpi *G, const mpi *A, const mpi *B );
/**
* \brief Modular inverse: X = A^-1 mod N
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param N Right-hand MPI
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
* POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil
POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N
*/
int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N );
/**
* \brief Miller-Rabin primality test
*
* \param X MPI to check
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful (probably prime),
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
* POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime
*/
int mpi_is_prime( mpi *X,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Prime number generation
*
* \param X Destination MPI
* \param nbits Required size of X in bits ( 3 <= nbits <= POLARSSL_MPI_MAX_BITS )
* \param dh_flag If 1, then (X-1)/2 will be prime too
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful (probably prime),
* POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
* POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
*/
int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int mpi_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* bignum.h */
+864
View File
@@ -0,0 +1,864 @@
/**
* \file bn_mul.h
*
* \brief Multi-precision integer library
*
* Copyright (C) 2006-2010, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* Multiply source vector [s] with b, add result
* to destination vector [d] and set carry c.
*
* Currently supports:
*
* . IA-32 (386+) . AMD64 / EM64T
* . IA-32 (SSE2) . Motorola 68000
* . PowerPC, 32-bit . MicroBlaze
* . PowerPC, 64-bit . TriCore
* . SPARC v8 . ARM v3+
* . Alpha . MIPS32
* . C, longlong . C, generic
*/
#ifndef POLARSSL_BN_MUL_H
#define POLARSSL_BN_MUL_H
#include "polarssl/bignum.h"
#if defined(POLARSSL_HAVE_ASM)
#if defined(__GNUC__)
#if defined(__i386__)
#define MULADDC_INIT \
__asm__( " \
movl %%ebx, %0; \
movl %5, %%esi; \
movl %6, %%edi; \
movl %7, %%ecx; \
movl %8, %%ebx; \
"
#define MULADDC_CORE \
" \
lodsl; \
mull %%ebx; \
addl %%ecx, %%eax; \
adcl $0, %%edx; \
addl (%%edi), %%eax; \
adcl $0, %%edx; \
movl %%edx, %%ecx; \
stosl; \
"
#if defined(POLARSSL_HAVE_SSE2)
#define MULADDC_HUIT \
" \
movd %%ecx, %%mm1; \
movd %%ebx, %%mm0; \
movd (%%edi), %%mm3; \
paddq %%mm3, %%mm1; \
movd (%%esi), %%mm2; \
pmuludq %%mm0, %%mm2; \
movd 4(%%esi), %%mm4; \
pmuludq %%mm0, %%mm4; \
movd 8(%%esi), %%mm6; \
pmuludq %%mm0, %%mm6; \
movd 12(%%esi), %%mm7; \
pmuludq %%mm0, %%mm7; \
paddq %%mm2, %%mm1; \
movd 4(%%edi), %%mm3; \
paddq %%mm4, %%mm3; \
movd 8(%%edi), %%mm5; \
paddq %%mm6, %%mm5; \
movd 12(%%edi), %%mm4; \
paddq %%mm4, %%mm7; \
movd %%mm1, (%%edi); \
movd 16(%%esi), %%mm2; \
pmuludq %%mm0, %%mm2; \
psrlq $32, %%mm1; \
movd 20(%%esi), %%mm4; \
pmuludq %%mm0, %%mm4; \
paddq %%mm3, %%mm1; \
movd 24(%%esi), %%mm6; \
pmuludq %%mm0, %%mm6; \
movd %%mm1, 4(%%edi); \
psrlq $32, %%mm1; \
movd 28(%%esi), %%mm3; \
pmuludq %%mm0, %%mm3; \
paddq %%mm5, %%mm1; \
movd 16(%%edi), %%mm5; \
paddq %%mm5, %%mm2; \
movd %%mm1, 8(%%edi); \
psrlq $32, %%mm1; \
paddq %%mm7, %%mm1; \
movd 20(%%edi), %%mm5; \
paddq %%mm5, %%mm4; \
movd %%mm1, 12(%%edi); \
psrlq $32, %%mm1; \
paddq %%mm2, %%mm1; \
movd 24(%%edi), %%mm5; \
paddq %%mm5, %%mm6; \
movd %%mm1, 16(%%edi); \
psrlq $32, %%mm1; \
paddq %%mm4, %%mm1; \
movd 28(%%edi), %%mm5; \
paddq %%mm5, %%mm3; \
movd %%mm1, 20(%%edi); \
psrlq $32, %%mm1; \
paddq %%mm6, %%mm1; \
movd %%mm1, 24(%%edi); \
psrlq $32, %%mm1; \
paddq %%mm3, %%mm1; \
movd %%mm1, 28(%%edi); \
addl $32, %%edi; \
addl $32, %%esi; \
psrlq $32, %%mm1; \
movd %%mm1, %%ecx; \
"
#define MULADDC_STOP \
" \
emms; \
movl %4, %%ebx; \
movl %%ecx, %1; \
movl %%edi, %2; \
movl %%esi, %3; \
" \
: "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
: "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
: "eax", "ecx", "edx", "esi", "edi" \
);
#else
#define MULADDC_STOP \
" \
movl %4, %%ebx; \
movl %%ecx, %1; \
movl %%edi, %2; \
movl %%esi, %3; \
" \
: "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
: "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
: "eax", "ecx", "edx", "esi", "edi" \
);
#endif /* SSE2 */
#endif /* i386 */
#if defined(__amd64__) || defined (__x86_64__)
#define MULADDC_INIT \
__asm__( "movq %0, %%rsi " :: "m" (s)); \
__asm__( "movq %0, %%rdi " :: "m" (d)); \
__asm__( "movq %0, %%rcx " :: "m" (c)); \
__asm__( "movq %0, %%rbx " :: "m" (b)); \
__asm__( "xorq %r8, %r8 " );
#define MULADDC_CORE \
__asm__( "movq (%rsi),%rax " ); \
__asm__( "mulq %rbx " ); \
__asm__( "addq $8, %rsi " ); \
__asm__( "addq %rcx, %rax " ); \
__asm__( "movq %r8, %rcx " ); \
__asm__( "adcq $0, %rdx " ); \
__asm__( "nop " ); \
__asm__( "addq %rax, (%rdi) " ); \
__asm__( "adcq %rdx, %rcx " ); \
__asm__( "addq $8, %rdi " );
#define MULADDC_STOP \
__asm__( "movq %%rcx, %0 " : "=m" (c)); \
__asm__( "movq %%rdi, %0 " : "=m" (d)); \
__asm__( "movq %%rsi, %0 " : "=m" (s) :: \
"rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
#endif /* AMD64 */
#if defined(__mc68020__) || defined(__mcpu32__)
#define MULADDC_INIT \
__asm__( "movl %0, %%a2 " :: "m" (s)); \
__asm__( "movl %0, %%a3 " :: "m" (d)); \
__asm__( "movl %0, %%d3 " :: "m" (c)); \
__asm__( "movl %0, %%d2 " :: "m" (b)); \
__asm__( "moveq #0, %d0 " );
#define MULADDC_CORE \
__asm__( "movel %a2@+, %d1 " ); \
__asm__( "mulul %d2, %d4:%d1 " ); \
__asm__( "addl %d3, %d1 " ); \
__asm__( "addxl %d0, %d4 " ); \
__asm__( "moveq #0, %d3 " ); \
__asm__( "addl %d1, %a3@+ " ); \
__asm__( "addxl %d4, %d3 " );
#define MULADDC_STOP \
__asm__( "movl %%d3, %0 " : "=m" (c)); \
__asm__( "movl %%a3, %0 " : "=m" (d)); \
__asm__( "movl %%a2, %0 " : "=m" (s) :: \
"d0", "d1", "d2", "d3", "d4", "a2", "a3" );
#define MULADDC_HUIT \
__asm__( "movel %a2@+, %d1 " ); \
__asm__( "mulul %d2, %d4:%d1 " ); \
__asm__( "addxl %d3, %d1 " ); \
__asm__( "addxl %d0, %d4 " ); \
__asm__( "addl %d1, %a3@+ " ); \
__asm__( "movel %a2@+, %d1 " ); \
__asm__( "mulul %d2, %d3:%d1 " ); \
__asm__( "addxl %d4, %d1 " ); \
__asm__( "addxl %d0, %d3 " ); \
__asm__( "addl %d1, %a3@+ " ); \
__asm__( "movel %a2@+, %d1 " ); \
__asm__( "mulul %d2, %d4:%d1 " ); \
__asm__( "addxl %d3, %d1 " ); \
__asm__( "addxl %d0, %d4 " ); \
__asm__( "addl %d1, %a3@+ " ); \
__asm__( "movel %a2@+, %d1 " ); \
__asm__( "mulul %d2, %d3:%d1 " ); \
__asm__( "addxl %d4, %d1 " ); \
__asm__( "addxl %d0, %d3 " ); \
__asm__( "addl %d1, %a3@+ " ); \
__asm__( "movel %a2@+, %d1 " ); \
__asm__( "mulul %d2, %d4:%d1 " ); \
__asm__( "addxl %d3, %d1 " ); \
__asm__( "addxl %d0, %d4 " ); \
__asm__( "addl %d1, %a3@+ " ); \
__asm__( "movel %a2@+, %d1 " ); \
__asm__( "mulul %d2, %d3:%d1 " ); \
__asm__( "addxl %d4, %d1 " ); \
__asm__( "addxl %d0, %d3 " ); \
__asm__( "addl %d1, %a3@+ " ); \
__asm__( "movel %a2@+, %d1 " ); \
__asm__( "mulul %d2, %d4:%d1 " ); \
__asm__( "addxl %d3, %d1 " ); \
__asm__( "addxl %d0, %d4 " ); \
__asm__( "addl %d1, %a3@+ " ); \
__asm__( "movel %a2@+, %d1 " ); \
__asm__( "mulul %d2, %d3:%d1 " ); \
__asm__( "addxl %d4, %d1 " ); \
__asm__( "addxl %d0, %d3 " ); \
__asm__( "addl %d1, %a3@+ " ); \
__asm__( "addxl %d0, %d3 " );
#endif /* MC68000 */
#if defined(__powerpc__) || defined(__ppc__)
#if defined(__powerpc64__) || defined(__ppc64__)
#if defined(__MACH__) && defined(__APPLE__)
#define MULADDC_INIT \
__asm__( "ld r3, %0 " :: "m" (s)); \
__asm__( "ld r4, %0 " :: "m" (d)); \
__asm__( "ld r5, %0 " :: "m" (c)); \
__asm__( "ld r6, %0 " :: "m" (b)); \
__asm__( "addi r3, r3, -8 " ); \
__asm__( "addi r4, r4, -8 " ); \
__asm__( "addic r5, r5, 0 " );
#define MULADDC_CORE \
__asm__( "ldu r7, 8(r3) " ); \
__asm__( "mulld r8, r7, r6 " ); \
__asm__( "mulhdu r9, r7, r6 " ); \
__asm__( "adde r8, r8, r5 " ); \
__asm__( "ld r7, 8(r4) " ); \
__asm__( "addze r5, r9 " ); \
__asm__( "addc r8, r8, r7 " ); \
__asm__( "stdu r8, 8(r4) " );
#define MULADDC_STOP \
__asm__( "addze r5, r5 " ); \
__asm__( "addi r4, r4, 8 " ); \
__asm__( "addi r3, r3, 8 " ); \
__asm__( "std r5, %0 " : "=m" (c)); \
__asm__( "std r4, %0 " : "=m" (d)); \
__asm__( "std r3, %0 " : "=m" (s) :: \
"r3", "r4", "r5", "r6", "r7", "r8", "r9" );
#else
#define MULADDC_INIT \
__asm__( "ld %%r3, %0 " :: "m" (s)); \
__asm__( "ld %%r4, %0 " :: "m" (d)); \
__asm__( "ld %%r5, %0 " :: "m" (c)); \
__asm__( "ld %%r6, %0 " :: "m" (b)); \
__asm__( "addi %r3, %r3, -8 " ); \
__asm__( "addi %r4, %r4, -8 " ); \
__asm__( "addic %r5, %r5, 0 " );
#define MULADDC_CORE \
__asm__( "ldu %r7, 8(%r3) " ); \
__asm__( "mulld %r8, %r7, %r6 " ); \
__asm__( "mulhdu %r9, %r7, %r6 " ); \
__asm__( "adde %r8, %r8, %r5 " ); \
__asm__( "ld %r7, 8(%r4) " ); \
__asm__( "addze %r5, %r9 " ); \
__asm__( "addc %r8, %r8, %r7 " ); \
__asm__( "stdu %r8, 8(%r4) " );
#define MULADDC_STOP \
__asm__( "addze %r5, %r5 " ); \
__asm__( "addi %r4, %r4, 8 " ); \
__asm__( "addi %r3, %r3, 8 " ); \
__asm__( "std %%r5, %0 " : "=m" (c)); \
__asm__( "std %%r4, %0 " : "=m" (d)); \
__asm__( "std %%r3, %0 " : "=m" (s) :: \
"r3", "r4", "r5", "r6", "r7", "r8", "r9" );
#endif
#else /* PPC32 */
#if defined(__MACH__) && defined(__APPLE__)
#define MULADDC_INIT \
__asm__( "lwz r3, %0 " :: "m" (s)); \
__asm__( "lwz r4, %0 " :: "m" (d)); \
__asm__( "lwz r5, %0 " :: "m" (c)); \
__asm__( "lwz r6, %0 " :: "m" (b)); \
__asm__( "addi r3, r3, -4 " ); \
__asm__( "addi r4, r4, -4 " ); \
__asm__( "addic r5, r5, 0 " );
#define MULADDC_CORE \
__asm__( "lwzu r7, 4(r3) " ); \
__asm__( "mullw r8, r7, r6 " ); \
__asm__( "mulhwu r9, r7, r6 " ); \
__asm__( "adde r8, r8, r5 " ); \
__asm__( "lwz r7, 4(r4) " ); \
__asm__( "addze r5, r9 " ); \
__asm__( "addc r8, r8, r7 " ); \
__asm__( "stwu r8, 4(r4) " );
#define MULADDC_STOP \
__asm__( "addze r5, r5 " ); \
__asm__( "addi r4, r4, 4 " ); \
__asm__( "addi r3, r3, 4 " ); \
__asm__( "stw r5, %0 " : "=m" (c)); \
__asm__( "stw r4, %0 " : "=m" (d)); \
__asm__( "stw r3, %0 " : "=m" (s) :: \
"r3", "r4", "r5", "r6", "r7", "r8", "r9" );
#else
#define MULADDC_INIT \
__asm__( "lwz %%r3, %0 " :: "m" (s)); \
__asm__( "lwz %%r4, %0 " :: "m" (d)); \
__asm__( "lwz %%r5, %0 " :: "m" (c)); \
__asm__( "lwz %%r6, %0 " :: "m" (b)); \
__asm__( "addi %r3, %r3, -4 " ); \
__asm__( "addi %r4, %r4, -4 " ); \
__asm__( "addic %r5, %r5, 0 " );
#define MULADDC_CORE \
__asm__( "lwzu %r7, 4(%r3) " ); \
__asm__( "mullw %r8, %r7, %r6 " ); \
__asm__( "mulhwu %r9, %r7, %r6 " ); \
__asm__( "adde %r8, %r8, %r5 " ); \
__asm__( "lwz %r7, 4(%r4) " ); \
__asm__( "addze %r5, %r9 " ); \
__asm__( "addc %r8, %r8, %r7 " ); \
__asm__( "stwu %r8, 4(%r4) " );
#define MULADDC_STOP \
__asm__( "addze %r5, %r5 " ); \
__asm__( "addi %r4, %r4, 4 " ); \
__asm__( "addi %r3, %r3, 4 " ); \
__asm__( "stw %%r5, %0 " : "=m" (c)); \
__asm__( "stw %%r4, %0 " : "=m" (d)); \
__asm__( "stw %%r3, %0 " : "=m" (s) :: \
"r3", "r4", "r5", "r6", "r7", "r8", "r9" );
#endif
#endif /* PPC32 */
#endif /* PPC64 */
#if defined(__sparc__) && defined(__sparc64__)
#define MULADDC_INIT \
__asm__( \
" \
ldx %3, %%o0; \
ldx %4, %%o1; \
ld %5, %%o2; \
ld %6, %%o3; \
"
#define MULADDC_CORE \
" \
ld [%%o0], %%o4; \
inc 4, %%o0; \
ld [%%o1], %%o5; \
umul %%o3, %%o4, %%o4; \
addcc %%o4, %%o2, %%o4; \
rd %%y, %%g1; \
addx %%g1, 0, %%g1; \
addcc %%o4, %%o5, %%o4; \
st %%o4, [%%o1]; \
addx %%g1, 0, %%o2; \
inc 4, %%o1; \
"
#define MULADDC_STOP \
" \
st %%o2, %0; \
stx %%o1, %1; \
stx %%o0, %2; \
" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "g1", "o0", "o1", "o2", "o3", "o4", \
"o5" \
);
#endif /* SPARCv9 */
#if defined(__sparc__) && !defined(__sparc64__)
#define MULADDC_INIT \
__asm__( \
" \
ld %3, %%o0; \
ld %4, %%o1; \
ld %5, %%o2; \
ld %6, %%o3; \
"
#define MULADDC_CORE \
" \
ld [%%o0], %%o4; \
inc 4, %%o0; \
ld [%%o1], %%o5; \
umul %%o3, %%o4, %%o4; \
addcc %%o4, %%o2, %%o4; \
rd %%y, %%g1; \
addx %%g1, 0, %%g1; \
addcc %%o4, %%o5, %%o4; \
st %%o4, [%%o1]; \
addx %%g1, 0, %%o2; \
inc 4, %%o1; \
"
#define MULADDC_STOP \
" \
st %%o2, %0; \
st %%o1, %1; \
st %%o0, %2; \
" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "g1", "o0", "o1", "o2", "o3", "o4", \
"o5" \
);
#endif /* SPARCv8 */
#if defined(__microblaze__) || defined(microblaze)
#define MULADDC_INIT \
__asm__( "lwi r3, %0 " :: "m" (s)); \
__asm__( "lwi r4, %0 " :: "m" (d)); \
__asm__( "lwi r5, %0 " :: "m" (c)); \
__asm__( "lwi r6, %0 " :: "m" (b)); \
__asm__( "andi r7, r6, 0xffff" ); \
__asm__( "bsrli r6, r6, 16 " );
#define MULADDC_CORE \
__asm__( "lhui r8, r3, 0 " ); \
__asm__( "addi r3, r3, 2 " ); \
__asm__( "lhui r9, r3, 0 " ); \
__asm__( "addi r3, r3, 2 " ); \
__asm__( "mul r10, r9, r6 " ); \
__asm__( "mul r11, r8, r7 " ); \
__asm__( "mul r12, r9, r7 " ); \
__asm__( "mul r13, r8, r6 " ); \
__asm__( "bsrli r8, r10, 16 " ); \
__asm__( "bsrli r9, r11, 16 " ); \
__asm__( "add r13, r13, r8 " ); \
__asm__( "add r13, r13, r9 " ); \
__asm__( "bslli r10, r10, 16 " ); \
__asm__( "bslli r11, r11, 16 " ); \
__asm__( "add r12, r12, r10 " ); \
__asm__( "addc r13, r13, r0 " ); \
__asm__( "add r12, r12, r11 " ); \
__asm__( "addc r13, r13, r0 " ); \
__asm__( "lwi r10, r4, 0 " ); \
__asm__( "add r12, r12, r10 " ); \
__asm__( "addc r13, r13, r0 " ); \
__asm__( "add r12, r12, r5 " ); \
__asm__( "addc r5, r13, r0 " ); \
__asm__( "swi r12, r4, 0 " ); \
__asm__( "addi r4, r4, 4 " );
#define MULADDC_STOP \
__asm__( "swi r5, %0 " : "=m" (c)); \
__asm__( "swi r4, %0 " : "=m" (d)); \
__asm__( "swi r3, %0 " : "=m" (s) :: \
"r3", "r4" , "r5" , "r6" , "r7" , "r8" , \
"r9", "r10", "r11", "r12", "r13" );
#endif /* MicroBlaze */
#if defined(__tricore__)
#define MULADDC_INIT \
__asm__( "ld.a %%a2, %0 " :: "m" (s)); \
__asm__( "ld.a %%a3, %0 " :: "m" (d)); \
__asm__( "ld.w %%d4, %0 " :: "m" (c)); \
__asm__( "ld.w %%d1, %0 " :: "m" (b)); \
__asm__( "xor %d5, %d5 " );
#define MULADDC_CORE \
__asm__( "ld.w %d0, [%a2+] " ); \
__asm__( "madd.u %e2, %e4, %d0, %d1 " ); \
__asm__( "ld.w %d0, [%a3] " ); \
__asm__( "addx %d2, %d2, %d0 " ); \
__asm__( "addc %d3, %d3, 0 " ); \
__asm__( "mov %d4, %d3 " ); \
__asm__( "st.w [%a3+], %d2 " );
#define MULADDC_STOP \
__asm__( "st.w %0, %%d4 " : "=m" (c)); \
__asm__( "st.a %0, %%a3 " : "=m" (d)); \
__asm__( "st.a %0, %%a2 " : "=m" (s) :: \
"d0", "d1", "e2", "d4", "a2", "a3" );
#endif /* TriCore */
#if defined(__arm__)
#if defined(__thumb__) && !defined(__thumb2__)
#define MULADDC_INIT \
__asm__( \
" \
ldr r0, %3; \
ldr r1, %4; \
ldr r2, %5; \
ldr r3, %6; \
lsr r7, r3, #16; \
mov r9, r7; \
lsl r7, r3, #16; \
lsr r7, r7, #16; \
mov r8, r7; \
"
#define MULADDC_CORE \
" \
ldmia r0!, {r6}; \
lsr r7, r6, #16; \
lsl r6, r6, #16; \
lsr r6, r6, #16; \
mov r4, r8; \
mul r4, r6; \
mov r3, r9; \
mul r6, r3; \
mov r5, r9; \
mul r5, r7; \
mov r3, r8; \
mul r7, r3; \
lsr r3, r6, #16; \
add r5, r5, r3; \
lsr r3, r7, #16; \
add r5, r5, r3; \
add r4, r4, r2; \
mov r2, #0; \
adc r5, r2; \
lsl r3, r6, #16; \
add r4, r4, r3; \
adc r5, r2; \
lsl r3, r7, #16; \
add r4, r4, r3; \
adc r5, r2; \
ldr r3, [r1]; \
add r4, r4, r3; \
adc r2, r5; \
stmia r1!, {r4}; \
"
#define MULADDC_STOP \
" \
str r2, %0; \
str r1, %1; \
str r0, %2; \
" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r0", "r1", "r2", "r3", "r4", "r5", \
"r6", "r7", "r8", "r9", "cc" \
);
#else
#define MULADDC_INIT \
__asm__( \
" \
ldr r0, %3; \
ldr r1, %4; \
ldr r2, %5; \
ldr r3, %6; \
"
#define MULADDC_CORE \
" \
ldr r4, [r0], #4; \
mov r5, #0; \
ldr r6, [r1]; \
umlal r2, r5, r3, r4; \
adds r7, r6, r2; \
adc r2, r5, #0; \
str r7, [r1], #4; \
"
#define MULADDC_STOP \
" \
str r2, %0; \
str r1, %1; \
str r0, %2; \
" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r0", "r1", "r2", "r3", "r4", "r5", \
"r6", "r7", "cc" \
);
#endif /* Thumb */
#endif /* ARMv3 */
#if defined(__alpha__)
#define MULADDC_INIT \
__asm__( "ldq $1, %0 " :: "m" (s)); \
__asm__( "ldq $2, %0 " :: "m" (d)); \
__asm__( "ldq $3, %0 " :: "m" (c)); \
__asm__( "ldq $4, %0 " :: "m" (b));
#define MULADDC_CORE \
__asm__( "ldq $6, 0($1) " ); \
__asm__( "addq $1, 8, $1 " ); \
__asm__( "mulq $6, $4, $7 " ); \
__asm__( "umulh $6, $4, $6 " ); \
__asm__( "addq $7, $3, $7 " ); \
__asm__( "cmpult $7, $3, $3 " ); \
__asm__( "ldq $5, 0($2) " ); \
__asm__( "addq $7, $5, $7 " ); \
__asm__( "cmpult $7, $5, $5 " ); \
__asm__( "stq $7, 0($2) " ); \
__asm__( "addq $2, 8, $2 " ); \
__asm__( "addq $6, $3, $3 " ); \
__asm__( "addq $5, $3, $3 " );
#define MULADDC_STOP \
__asm__( "stq $3, %0 " : "=m" (c)); \
__asm__( "stq $2, %0 " : "=m" (d)); \
__asm__( "stq $1, %0 " : "=m" (s) :: \
"$1", "$2", "$3", "$4", "$5", "$6", "$7" );
#endif /* Alpha */
#if defined(__mips__)
#define MULADDC_INIT \
__asm__( "lw $10, %0 " :: "m" (s)); \
__asm__( "lw $11, %0 " :: "m" (d)); \
__asm__( "lw $12, %0 " :: "m" (c)); \
__asm__( "lw $13, %0 " :: "m" (b));
#define MULADDC_CORE \
__asm__( "lw $14, 0($10) " ); \
__asm__( "multu $13, $14 " ); \
__asm__( "addi $10, $10, 4 " ); \
__asm__( "mflo $14 " ); \
__asm__( "mfhi $9 " ); \
__asm__( "addu $14, $12, $14 " ); \
__asm__( "lw $15, 0($11) " ); \
__asm__( "sltu $12, $14, $12 " ); \
__asm__( "addu $15, $14, $15 " ); \
__asm__( "sltu $14, $15, $14 " ); \
__asm__( "addu $12, $12, $9 " ); \
__asm__( "sw $15, 0($11) " ); \
__asm__( "addu $12, $12, $14 " ); \
__asm__( "addi $11, $11, 4 " );
#define MULADDC_STOP \
__asm__( "sw $12, %0 " : "=m" (c)); \
__asm__( "sw $11, %0 " : "=m" (d)); \
__asm__( "sw $10, %0 " : "=m" (s) :: \
"$9", "$10", "$11", "$12", "$13", "$14", "$15" );
#endif /* MIPS */
#endif /* GNUC */
#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
#define MULADDC_INIT \
____asm__ mov esi, s \
____asm__ mov edi, d \
____asm__ mov ecx, c \
____asm__ mov ebx, b
#define MULADDC_CORE \
____asm__ lodsd \
____asm__ mul ebx \
____asm__ add eax, ecx \
____asm__ adc edx, 0 \
____asm__ add eax, [edi] \
____asm__ adc edx, 0 \
____asm__ mov ecx, edx \
____asm__ stosd
#if defined(POLARSSL_HAVE_SSE2)
#define EMIT ____asm__ _emit
#define MULADDC_HUIT \
EMIT 0x0F EMIT 0x6E EMIT 0xC9 \
EMIT 0x0F EMIT 0x6E EMIT 0xC3 \
EMIT 0x0F EMIT 0x6E EMIT 0x1F \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x6E EMIT 0x16 \
EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \
EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \
EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \
EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \
EMIT 0x0F EMIT 0xD4 EMIT 0xDC \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \
EMIT 0x0F EMIT 0xD4 EMIT 0xEE \
EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \
EMIT 0x0F EMIT 0xD4 EMIT 0xFC \
EMIT 0x0F EMIT 0x7E EMIT 0x0F \
EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \
EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \
EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \
EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \
EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCD \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \
EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCF \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \
EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \
EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCC \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \
EMIT 0x0F EMIT 0xD4 EMIT 0xDD \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCE \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \
EMIT 0x83 EMIT 0xC7 EMIT 0x20 \
EMIT 0x83 EMIT 0xC6 EMIT 0x20 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x7E EMIT 0xC9
#define MULADDC_STOP \
EMIT 0x0F EMIT 0x77 \
____asm__ mov c, ecx \
____asm__ mov d, edi \
____asm__ mov s, esi \
#else
#define MULADDC_STOP \
____asm__ mov c, ecx \
____asm__ mov d, edi \
____asm__ mov s, esi \
#endif /* SSE2 */
#endif /* MSVC */
#endif /* POLARSSL_HAVE_ASM */
#if !defined(MULADDC_CORE)
#if defined(POLARSSL_HAVE_UDBL)
#define MULADDC_INIT \
{ \
t_udbl r; \
t_uint r0, r1;
#define MULADDC_CORE \
r = *(s++) * (t_udbl) b; \
r0 = r; \
r1 = r >> biL; \
r0 += c; r1 += (r0 < c); \
r0 += *d; r1 += (r0 < *d); \
c = r1; *(d++) = r0;
#define MULADDC_STOP \
}
#else
#define MULADDC_INIT \
{ \
t_uint s0, s1, b0, b1; \
t_uint r0, r1, rx, ry; \
b0 = ( b << biH ) >> biH; \
b1 = ( b >> biH );
#define MULADDC_CORE \
s0 = ( *s << biH ) >> biH; \
s1 = ( *s >> biH ); s++; \
rx = s0 * b1; r0 = s0 * b0; \
ry = s1 * b0; r1 = s1 * b1; \
r1 += ( rx >> biH ); \
r1 += ( ry >> biH ); \
rx <<= biH; ry <<= biH; \
r0 += rx; r1 += (r0 < rx); \
r0 += ry; r1 += (r0 < ry); \
r0 += c; r1 += (r0 < c); \
r0 += *d; r1 += (r0 < *d); \
c = r1; *(d++) = r0;
#define MULADDC_STOP \
}
#endif /* C (generic) */
#endif /* C (longlong) */
#endif /* bn_mul.h */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+597
View File
@@ -0,0 +1,597 @@
/**
* \file rsa.h
*
* \brief The RSA public-key cryptosystem
*
* Copyright (C) 2006-2010, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_RSA_H
#define POLARSSL_RSA_H
#include "polarssl/bignum.h"
/*
* RSA Error codes
*/
#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */
#define POLARSSL_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */
#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */
#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the libraries validity check. */
#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */
#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */
#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */
#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */
#define POLARSSL_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */
/*
* PKCS#1 constants
*/
#define SIG_RSA_RAW 0
#define SIG_RSA_MD2 2
#define SIG_RSA_MD4 3
#define SIG_RSA_MD5 4
#define SIG_RSA_SHA1 5
#define SIG_RSA_SHA224 14
#define SIG_RSA_SHA256 11
#define SIG_RSA_SHA384 12
#define SIG_RSA_SHA512 13
#define RSA_PUBLIC 0
#define RSA_PRIVATE 1
#define RSA_PKCS_V15 0
#define RSA_PKCS_V21 1
#define RSA_SIGN 1
#define RSA_CRYPT 2
#define ASN1_STR_CONSTRUCTED_SEQUENCE "\x30"
#define ASN1_STR_NULL "\x05"
#define ASN1_STR_OID "\x06"
#define ASN1_STR_OCTET_STRING "\x04"
#define OID_DIGEST_ALG_MDX "\x2A\x86\x48\x86\xF7\x0D\x02\x00"
#define OID_HASH_ALG_SHA1 "\x2b\x0e\x03\x02\x1a"
#define OID_HASH_ALG_SHA2X "\x60\x86\x48\x01\x65\x03\x04\x02\x00"
#define OID_ISO_MEMBER_BODIES "\x2a"
#define OID_ISO_IDENTIFIED_ORG "\x2b"
/*
* ISO Member bodies OID parts
*/
#define OID_COUNTRY_US "\x86\x48"
#define OID_RSA_DATA_SECURITY "\x86\xf7\x0d"
/*
* ISO Identified organization OID parts
*/
#define OID_OIW_SECSIG_SHA1 "\x0e\x03\x02\x1a"
/*
* DigestInfo ::= SEQUENCE {
* digestAlgorithm DigestAlgorithmIdentifier,
* digest Digest }
*
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier
*
* Digest ::= OCTET STRING
*/
#define ASN1_HASH_MDX \
( \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x20" \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x0C" \
ASN1_STR_OID "\x08" \
OID_DIGEST_ALG_MDX \
ASN1_STR_NULL "\x00" \
ASN1_STR_OCTET_STRING "\x10" \
)
#define ASN1_HASH_SHA1 \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x21" \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x09" \
ASN1_STR_OID "\x05" \
OID_HASH_ALG_SHA1 \
ASN1_STR_NULL "\x00" \
ASN1_STR_OCTET_STRING "\x14"
#define ASN1_HASH_SHA1_ALT \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x1F" \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x07" \
ASN1_STR_OID "\x05" \
OID_HASH_ALG_SHA1 \
ASN1_STR_OCTET_STRING "\x14"
#define ASN1_HASH_SHA2X \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x11" \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x0d" \
ASN1_STR_OID "\x09" \
OID_HASH_ALG_SHA2X \
ASN1_STR_NULL "\x00" \
ASN1_STR_OCTET_STRING "\x00"
/**
* \brief RSA context structure
*/
typedef struct
{
int ver; /*!< always 0 */
size_t len; /*!< size(N) in chars */
mpi N; /*!< public modulus */
mpi E; /*!< public exponent */
mpi D; /*!< private exponent */
mpi P; /*!< 1st prime factor */
mpi Q; /*!< 2nd prime factor */
mpi DP; /*!< D % (P - 1) */
mpi DQ; /*!< D % (Q - 1) */
mpi QP; /*!< 1 / (Q % P) */
mpi RN; /*!< cached R^2 mod N */
mpi RP; /*!< cached R^2 mod P */
mpi RQ; /*!< cached R^2 mod Q */
int padding; /*!< RSA_PKCS_V15 for 1.5 padding and
RSA_PKCS_v21 for OAEP/PSS */
int hash_id; /*!< Hash identifier of md_type_t as
specified in the md.h header file
for the EME-OAEP and EMSA-PSS
encoding */
}
rsa_context;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Initialize an RSA context
*
* Note: Set padding to RSA_PKCS_V21 for the RSAES-OAEP
* encryption scheme and the RSASSA-PSS signature scheme.
*
* \param ctx RSA context to be initialized
* \param padding RSA_PKCS_V15 or RSA_PKCS_V21
* \param hash_id RSA_PKCS_V21 hash identifier
*
* \note The hash_id parameter is actually ignored
* when using RSA_PKCS_V15 padding.
*/
void rsa_init( rsa_context *ctx,
int padding,
int hash_id);
/**
* \brief Generate an RSA keypair
*
* \param ctx RSA context that will hold the key
* \param f_rng RNG function
* \param p_rng RNG parameter
* \param nbits size of the public key in bits
* \param exponent public exponent (e.g., 65537)
*
* \note rsa_init() must be called beforehand to setup
* the RSA context.
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*/
int rsa_gen_key( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
unsigned int nbits, int exponent );
/**
* \brief Check a public RSA key
*
* \param ctx RSA context to be checked
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*/
int rsa_check_pubkey( const rsa_context *ctx );
/**
* \brief Check a private RSA key
*
* \param ctx RSA context to be checked
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*/
int rsa_check_privkey( const rsa_context *ctx );
/**
* \brief Do an RSA public key operation
*
* \param ctx RSA context
* \param input input buffer
* \param output output buffer
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note This function does NOT take care of message
* padding. Also, be sure to set input[0] = 0 or assure that
* input is smaller than N.
*
* \note The input and output buffers must be large
* enough (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_public( rsa_context *ctx,
const unsigned char *input,
unsigned char *output );
/**
* \brief Do an RSA private key operation
*
* \param ctx RSA context
* \param input input buffer
* \param output output buffer
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The input and output buffers must be large
* enough (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_private( rsa_context *ctx,
const unsigned char *input,
unsigned char *output );
/**
* \brief Generic wrapper to perform a PKCS#1 encryption using the
* mode from the context. Add the message padding, then do an
* RSA operation.
*
* \param ctx RSA context
* \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding)
* \param p_rng RNG parameter
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param ilen contains the plaintext length
* \param input buffer holding the data to be encrypted
* \param output buffer that will hold the ciphertext
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The output buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_pkcs1_encrypt( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode, size_t ilen,
const unsigned char *input,
unsigned char *output );
/**
* \brief Perform a PKCS#1 v1.5 encryption (RSAES-PKCS1-v1_5-ENCRYPT)
*
* \param ctx RSA context
* \param f_rng RNG function (Needed for padding)
* \param p_rng RNG parameter
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param ilen contains the plaintext length
* \param input buffer holding the data to be encrypted
* \param output buffer that will hold the ciphertext
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The output buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_rsaes_pkcs1_v15_encrypt( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode, size_t ilen,
const unsigned char *input,
unsigned char *output );
/**
* \brief Perform a PKCS#1 v2.1 OAEP encryption (RSAES-OAEP-ENCRYPT)
*
* \param ctx RSA context
* \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding)
* \param p_rng RNG parameter
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param label buffer holding the custom label to use
* \param label_len contains the label length
* \param ilen contains the plaintext length
* \param input buffer holding the data to be encrypted
* \param output buffer that will hold the ciphertext
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The output buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_rsaes_oaep_encrypt( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode,
const unsigned char *label, size_t label_len,
size_t ilen,
const unsigned char *input,
unsigned char *output );
/**
* \brief Generic wrapper to perform a PKCS#1 decryption using the
* mode from the context. Do an RSA operation, then remove
* the message padding
*
* \param ctx RSA context
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param olen will contain the plaintext length
* \param input buffer holding the encrypted data
* \param output buffer that will hold the plaintext
* \param output_max_len maximum length of the output buffer
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The output buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
* an error is thrown.
*/
int rsa_pkcs1_decrypt( rsa_context *ctx,
int mode, size_t *olen,
const unsigned char *input,
unsigned char *output,
size_t output_max_len );
/**
* \brief Perform a PKCS#1 v1.5 decryption (RSAES-PKCS1-v1_5-DECRYPT)
*
* \param ctx RSA context
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param olen will contain the plaintext length
* \param input buffer holding the encrypted data
* \param output buffer that will hold the plaintext
* \param output_max_len maximum length of the output buffer
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The output buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
* an error is thrown.
*/
int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx,
int mode, size_t *olen,
const unsigned char *input,
unsigned char *output,
size_t output_max_len );
/**
* \brief Perform a PKCS#1 v2.1 OAEP decryption (RSAES-OAEP-DECRYPT)
*
* \param ctx RSA context
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param label buffer holding the custom label to use
* \param label_len contains the label length
* \param olen will contain the plaintext length
* \param input buffer holding the encrypted data
* \param output buffer that will hold the plaintext
* \param output_max_len maximum length of the output buffer
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The output buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
* an error is thrown.
*/
int rsa_rsaes_oaep_decrypt( rsa_context *ctx,
int mode,
const unsigned char *label, size_t label_len,
size_t *olen,
const unsigned char *input,
unsigned char *output,
size_t output_max_len );
/**
* \brief Generic wrapper to perform a PKCS#1 signature using the
* mode from the context. Do a private RSA operation to sign
* a message digest
*
* \param ctx RSA context
* \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding)
* \param p_rng RNG parameter
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
* \param hashlen message digest length (for SIG_RSA_RAW only)
* \param hash buffer holding the message digest
* \param sig buffer that will hold the ciphertext
*
* \return 0 if the signing operation was successful,
* or an POLARSSL_ERR_RSA_XXX error code
*
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*
* \note In case of PKCS#1 v2.1 encoding keep in mind that
* the hash_id in the RSA context is the one used for the
* encoding. hash_id in the function call is the type of hash
* that is encoded. According to RFC 3447 it is advised to
* keep both hashes the same.
*/
int rsa_pkcs1_sign( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig );
/**
* \brief Perform a PKCS#1 v1.5 signature (RSASSA-PKCS1-v1_5-SIGN)
*
* \param ctx RSA context
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
* \param hashlen message digest length (for SIG_RSA_RAW only)
* \param hash buffer holding the message digest
* \param sig buffer that will hold the ciphertext
*
* \return 0 if the signing operation was successful,
* or an POLARSSL_ERR_RSA_XXX error code
*
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig );
/**
* \brief Perform a PKCS#1 v2.1 PSS signature (RSASSA-PSS-SIGN)
*
* \param ctx RSA context
* \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding)
* \param p_rng RNG parameter
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
* \param hashlen message digest length (for SIG_RSA_RAW only)
* \param hash buffer holding the message digest
* \param sig buffer that will hold the ciphertext
*
* \return 0 if the signing operation was successful,
* or an POLARSSL_ERR_RSA_XXX error code
*
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*
* \note In case of PKCS#1 v2.1 encoding keep in mind that
* the hash_id in the RSA context is the one used for the
* encoding. hash_id in the function call is the type of hash
* that is encoded. According to RFC 3447 it is advised to
* keep both hashes the same.
*/
int rsa_rsassa_pss_sign( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig );
/**
* \brief Generic wrapper to perform a PKCS#1 verification using the
* mode from the context. Do a public RSA operation and check
* the message digest
*
* \param ctx points to an RSA public key
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
* \param hashlen message digest length (for SIG_RSA_RAW only)
* \param hash buffer holding the message digest
* \param sig buffer holding the ciphertext
*
* \return 0 if the verify operation was successful,
* or an POLARSSL_ERR_RSA_XXX error code
*
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*
* \note In case of PKCS#1 v2.1 encoding keep in mind that
* the hash_id in the RSA context is the one used for the
* verification. hash_id in the function call is the type of hash
* that is verified. According to RFC 3447 it is advised to
* keep both hashes the same.
*/
int rsa_pkcs1_verify( rsa_context *ctx,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
const unsigned char *sig );
/**
* \brief Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY)
*
* \param ctx points to an RSA public key
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
* \param hashlen message digest length (for SIG_RSA_RAW only)
* \param hash buffer holding the message digest
* \param sig buffer holding the ciphertext
*
* \return 0 if the verify operation was successful,
* or an POLARSSL_ERR_RSA_XXX error code
*
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
const unsigned char *sig );
/**
* \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY)
* \brief Do a public RSA and check the message digest
*
* \param ctx points to an RSA public key
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
* \param hashlen message digest length (for SIG_RSA_RAW only)
* \param hash buffer holding the message digest
* \param sig buffer holding the ciphertext
*
* \return 0 if the verify operation was successful,
* or an POLARSSL_ERR_RSA_XXX error code
*
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*
* \note In case of PKCS#1 v2.1 encoding keep in mind that
* the hash_id in the RSA context is the one used for the
* verification. hash_id in the function call is the type of hash
* that is verified. According to RFC 3447 it is advised to
* keep both hashes the same.
*/
int rsa_rsassa_pss_verify( rsa_context *ctx,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
const unsigned char *sig );
/**
* \brief Free the components of an RSA key
*
* \param ctx RSA Context to free
*/
void rsa_free( rsa_context *ctx );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int rsa_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* rsa.h */
+624
View File
@@ -0,0 +1,624 @@
/*
* FIPS-180-1 compliant SHA-1 implementation
*
* Copyright (C) 2006-2013, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The SHA-1 standard was published by NIST in 1993.
*
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*/
#include "polarssl/config.h"
#if defined(POLARSSL_SHA1_C)
#include "polarssl/sha1.h"
#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
#include <stdio.h>
#endif
#if !defined(POLARSSL_SHA1_ALT)
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
/*
* SHA-1 context setup
*/
void sha1_starts( sha1_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
}
void sha1_process( sha1_context *ctx, const unsigned char data[64] )
{
uint32_t temp, W[16], A, B, C, D, E;
GET_UINT32_BE( W[ 0], data, 0 );
GET_UINT32_BE( W[ 1], data, 4 );
GET_UINT32_BE( W[ 2], data, 8 );
GET_UINT32_BE( W[ 3], data, 12 );
GET_UINT32_BE( W[ 4], data, 16 );
GET_UINT32_BE( W[ 5], data, 20 );
GET_UINT32_BE( W[ 6], data, 24 );
GET_UINT32_BE( W[ 7], data, 28 );
GET_UINT32_BE( W[ 8], data, 32 );
GET_UINT32_BE( W[ 9], data, 36 );
GET_UINT32_BE( W[10], data, 40 );
GET_UINT32_BE( W[11], data, 44 );
GET_UINT32_BE( W[12], data, 48 );
GET_UINT32_BE( W[13], data, 52 );
GET_UINT32_BE( W[14], data, 56 );
GET_UINT32_BE( W[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
)
#define P(a,b,c,d,e,x) \
{ \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P( A, B, C, D, E, W[0] );
P( E, A, B, C, D, W[1] );
P( D, E, A, B, C, W[2] );
P( C, D, E, A, B, W[3] );
P( B, C, D, E, A, W[4] );
P( A, B, C, D, E, W[5] );
P( E, A, B, C, D, W[6] );
P( D, E, A, B, C, W[7] );
P( C, D, E, A, B, W[8] );
P( B, C, D, E, A, W[9] );
P( A, B, C, D, E, W[10] );
P( E, A, B, C, D, W[11] );
P( D, E, A, B, C, W[12] );
P( C, D, E, A, B, W[13] );
P( B, C, D, E, A, W[14] );
P( A, B, C, D, E, W[15] );
P( E, A, B, C, D, R(16) );
P( D, E, A, B, C, R(17) );
P( C, D, E, A, B, R(18) );
P( B, C, D, E, A, R(19) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P( A, B, C, D, E, R(20) );
P( E, A, B, C, D, R(21) );
P( D, E, A, B, C, R(22) );
P( C, D, E, A, B, R(23) );
P( B, C, D, E, A, R(24) );
P( A, B, C, D, E, R(25) );
P( E, A, B, C, D, R(26) );
P( D, E, A, B, C, R(27) );
P( C, D, E, A, B, R(28) );
P( B, C, D, E, A, R(29) );
P( A, B, C, D, E, R(30) );
P( E, A, B, C, D, R(31) );
P( D, E, A, B, C, R(32) );
P( C, D, E, A, B, R(33) );
P( B, C, D, E, A, R(34) );
P( A, B, C, D, E, R(35) );
P( E, A, B, C, D, R(36) );
P( D, E, A, B, C, R(37) );
P( C, D, E, A, B, R(38) );
P( B, C, D, E, A, R(39) );
#undef K
#undef F
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P( A, B, C, D, E, R(40) );
P( E, A, B, C, D, R(41) );
P( D, E, A, B, C, R(42) );
P( C, D, E, A, B, R(43) );
P( B, C, D, E, A, R(44) );
P( A, B, C, D, E, R(45) );
P( E, A, B, C, D, R(46) );
P( D, E, A, B, C, R(47) );
P( C, D, E, A, B, R(48) );
P( B, C, D, E, A, R(49) );
P( A, B, C, D, E, R(50) );
P( E, A, B, C, D, R(51) );
P( D, E, A, B, C, R(52) );
P( C, D, E, A, B, R(53) );
P( B, C, D, E, A, R(54) );
P( A, B, C, D, E, R(55) );
P( E, A, B, C, D, R(56) );
P( D, E, A, B, C, R(57) );
P( C, D, E, A, B, R(58) );
P( B, C, D, E, A, R(59) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P( A, B, C, D, E, R(60) );
P( E, A, B, C, D, R(61) );
P( D, E, A, B, C, R(62) );
P( C, D, E, A, B, R(63) );
P( B, C, D, E, A, R(64) );
P( A, B, C, D, E, R(65) );
P( E, A, B, C, D, R(66) );
P( D, E, A, B, C, R(67) );
P( C, D, E, A, B, R(68) );
P( B, C, D, E, A, R(69) );
P( A, B, C, D, E, R(70) );
P( E, A, B, C, D, R(71) );
P( D, E, A, B, C, R(72) );
P( C, D, E, A, B, R(73) );
P( B, C, D, E, A, R(74) );
P( A, B, C, D, E, R(75) );
P( E, A, B, C, D, R(76) );
P( D, E, A, B, C, R(77) );
P( C, D, E, A, B, R(78) );
P( B, C, D, E, A, R(79) );
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
/*
* SHA-1 process buffer
*/
void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
{
size_t fill;
uint32_t left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
sha1_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
sha1_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha1_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-1 final digest
*/
void sha1_finish( sha1_context *ctx, unsigned char output[20] )
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
sha1_update( ctx, sha1_padding, padn );
sha1_update( ctx, msglen, 8 );
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
PUT_UINT32_BE( ctx->state[3], output, 12 );
PUT_UINT32_BE( ctx->state[4], output, 16 );
}
#endif /* !POLARSSL_SHA1_ALT */
/*
* output = SHA-1( input buffer )
*/
void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
{
sha1_context ctx;
sha1_starts( &ctx );
sha1_update( &ctx, input, ilen );
sha1_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha1_context ) );
}
#if defined(POLARSSL_FS_IO)
/*
* output = SHA-1( file contents )
*/
int sha1_file( const char *path, unsigned char output[20] )
{
FILE *f;
size_t n;
sha1_context ctx;
unsigned char buf[1024];
if( ( f = fopen( path, "rb" ) ) == NULL )
return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
sha1_starts( &ctx );
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
sha1_update( &ctx, buf, n );
sha1_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha1_context ) );
if( ferror( f ) != 0 )
{
fclose( f );
return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
}
fclose( f );
return( 0 );
}
#endif /* POLARSSL_FS_IO */
/*
* SHA-1 HMAC context setup
*/
void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen )
{
size_t i;
unsigned char sum[20];
if( keylen > 64 )
{
sha1( key, keylen, sum );
keylen = 20;
key = sum;
}
memset( ctx->ipad, 0x36, 64 );
memset( ctx->opad, 0x5C, 64 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
sha1_starts( ctx );
sha1_update( ctx, ctx->ipad, 64 );
memset( sum, 0, sizeof( sum ) );
}
/*
* SHA-1 HMAC process buffer
*/
void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
{
sha1_update( ctx, input, ilen );
}
/*
* SHA-1 HMAC final digest
*/
void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
{
unsigned char tmpbuf[20];
sha1_finish( ctx, tmpbuf );
sha1_starts( ctx );
sha1_update( ctx, ctx->opad, 64 );
sha1_update( ctx, tmpbuf, 20 );
sha1_finish( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* SHA1 HMAC context reset
*/
void sha1_hmac_reset( sha1_context *ctx )
{
sha1_starts( ctx );
sha1_update( ctx, ctx->ipad, 64 );
}
/*
* output = HMAC-SHA-1( hmac key, input buffer )
*/
void sha1_hmac( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char output[20] )
{
sha1_context ctx;
sha1_hmac_starts( &ctx, key, keylen );
sha1_hmac_update( &ctx, input, ilen );
sha1_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha1_context ) );
}
#if defined(POLARSSL_SELF_TEST)
/*
* FIPS-180-1 test vectors
*/
static unsigned char sha1_test_buf[3][57] =
{
{ "abc" },
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
{ "" }
};
static const int sha1_test_buflen[3] =
{
3, 56, 1000
};
static const unsigned char sha1_test_sum[3][20] =
{
{ 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
{ 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
{ 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
};
/*
* RFC 2202 test vectors
*/
static unsigned char sha1_hmac_test_key[7][26] =
{
{ "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
"\x0B\x0B\x0B\x0B" },
{ "Jefe" },
{ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
"\xAA\xAA\xAA\xAA" },
{ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
{ "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
"\x0C\x0C\x0C\x0C" },
{ "" }, /* 0xAA 80 times */
{ "" }
};
static const int sha1_hmac_test_keylen[7] =
{
20, 4, 20, 25, 20, 80, 80
};
static unsigned char sha1_hmac_test_buf[7][74] =
{
{ "Hi There" },
{ "what do ya want for nothing?" },
{ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
{ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
{ "Test With Truncation" },
{ "Test Using Larger Than Block-Size Key - Hash Key First" },
{ "Test Using Larger Than Block-Size Key and Larger"
" Than One Block-Size Data" }
};
static const int sha1_hmac_test_buflen[7] =
{
8, 28, 50, 50, 20, 54, 73
};
static const unsigned char sha1_hmac_test_sum[7][20] =
{
{ 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,
0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 },
{ 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,
0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 },
{ 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,
0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 },
{ 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,
0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA },
{ 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,
0x7B, 0xE1 },
{ 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,
0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 },
{ 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,
0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 }
};
/*
* Checkup routine
*/
int sha1_self_test( int verbose )
{
int i, j, buflen;
unsigned char buf[1024];
unsigned char sha1sum[20];
sha1_context ctx;
/*
* SHA-1
*/
for( i = 0; i < 3; i++ )
{
if( verbose != 0 )
printf( " SHA-1 test #%d: ", i + 1 );
sha1_starts( &ctx );
if( i == 2 )
{
memset( buf, 'a', buflen = 1000 );
for( j = 0; j < 1000; j++ )
sha1_update( &ctx, buf, buflen );
}
else
sha1_update( &ctx, sha1_test_buf[i],
sha1_test_buflen[i] );
sha1_finish( &ctx, sha1sum );
if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
for( i = 0; i < 7; i++ )
{
if( verbose != 0 )
printf( " HMAC-SHA-1 test #%d: ", i + 1 );
if( i == 5 || i == 6 )
{
memset( buf, '\xAA', buflen = 80 );
sha1_hmac_starts( &ctx, buf, buflen );
}
else
sha1_hmac_starts( &ctx, sha1_hmac_test_key[i],
sha1_hmac_test_keylen[i] );
sha1_hmac_update( &ctx, sha1_hmac_test_buf[i],
sha1_hmac_test_buflen[i] );
sha1_hmac_finish( &ctx, sha1sum );
buflen = ( i == 4 ) ? 12 : 20;
if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
return( 0 );
}
#endif
#endif
+180
View File
@@ -0,0 +1,180 @@
/**
* \file sha1.h
*
* \brief SHA-1 cryptographic hash function
*
* Copyright (C) 2006-2013, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_SHA1_H
#define POLARSSL_SHA1_H
#include "polarssl/config.h"
#include <string.h>
#ifdef _MSC_VER
#include <basetsd.h>
typedef UINT32 uint32_t;
#else
#include <inttypes.h>
#endif
#define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */
#if !defined(POLARSSL_SHA1_ALT)
// Regular implementation
//
/**
* \brief SHA-1 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
unsigned char ipad[64]; /*!< HMAC: inner padding */
unsigned char opad[64]; /*!< HMAC: outer padding */
}
sha1_context;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*/
void sha1_starts( sha1_context *ctx );
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-1 final digest
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*/
void sha1_finish( sha1_context *ctx, unsigned char output[20] );
/* Internal use */
void sha1_process( sha1_context *ctx, const unsigned char data[64] );
#ifdef __cplusplus
}
#endif
#else /* POLARSSL_SHA1_ALT */
#include "polarssl/sha1_alt.h"
#endif /* POLARSSL_SHA1_ALT */
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Output = SHA-1( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-1 checksum result
*/
void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] );
/**
* \brief Output = SHA-1( file contents )
*
* \param path input file name
* \param output SHA-1 checksum result
*
* \return 0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR
*/
int sha1_file( const char *path, unsigned char output[20] );
/**
* \brief SHA-1 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen );
/**
* \brief SHA-1 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-1 HMAC final digest
*
* \param ctx HMAC context
* \param output SHA-1 HMAC checksum result
*/
void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );
/**
* \brief SHA-1 HMAC context reset
*
* \param ctx HMAC context to be reset
*/
void sha1_hmac_reset( sha1_context *ctx );
/**
* \brief Output = HMAC-SHA-1( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-SHA-1 result
*/
void sha1_hmac( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char output[20] );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int sha1_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* sha1.h */
+705
View File
@@ -0,0 +1,705 @@
/*
* FIPS-180-2 compliant SHA-256 implementation
*
* Copyright (C) 2006-2013, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#include "polarssl/config.h"
#if defined(POLARSSL_SHA2_C)
#include "polarssl/sha2.h"
#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
#include <stdio.h>
#endif
#if !defined(POLARSSL_SHA2_ALT)
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
/*
* SHA-256 context setup
*/
void sha2_starts( sha2_context *ctx, int is224 )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if( is224 == 0 )
{
/* SHA-256 */
ctx->state[0] = 0x6A09E667;
ctx->state[1] = 0xBB67AE85;
ctx->state[2] = 0x3C6EF372;
ctx->state[3] = 0xA54FF53A;
ctx->state[4] = 0x510E527F;
ctx->state[5] = 0x9B05688C;
ctx->state[6] = 0x1F83D9AB;
ctx->state[7] = 0x5BE0CD19;
}
else
{
/* SHA-224 */
ctx->state[0] = 0xC1059ED8;
ctx->state[1] = 0x367CD507;
ctx->state[2] = 0x3070DD17;
ctx->state[3] = 0xF70E5939;
ctx->state[4] = 0xFFC00B31;
ctx->state[5] = 0x68581511;
ctx->state[6] = 0x64F98FA7;
ctx->state[7] = 0xBEFA4FA4;
}
ctx->is224 = is224;
}
void sha2_process( sha2_context *ctx, const unsigned char data[64] )
{
uint32_t temp1, temp2, W[64];
uint32_t A, B, C, D, E, F, G, H;
GET_UINT32_BE( W[ 0], data, 0 );
GET_UINT32_BE( W[ 1], data, 4 );
GET_UINT32_BE( W[ 2], data, 8 );
GET_UINT32_BE( W[ 3], data, 12 );
GET_UINT32_BE( W[ 4], data, 16 );
GET_UINT32_BE( W[ 5], data, 20 );
GET_UINT32_BE( W[ 6], data, 24 );
GET_UINT32_BE( W[ 7], data, 28 );
GET_UINT32_BE( W[ 8], data, 32 );
GET_UINT32_BE( W[ 9], data, 36 );
GET_UINT32_BE( W[10], data, 40 );
GET_UINT32_BE( W[11], data, 44 );
GET_UINT32_BE( W[12], data, 48 );
GET_UINT32_BE( W[13], data, 52 );
GET_UINT32_BE( W[14], data, 56 );
GET_UINT32_BE( W[15], data, 60 );
#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define R(t) \
( \
W[t] = S1(W[t - 2]) + W[t - 7] + \
S0(W[t - 15]) + W[t - 16] \
)
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );
P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );
P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );
P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );
P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );
P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );
P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );
P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );
P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );
P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );
P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );
P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );
P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );
P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );
P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );
P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );
P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );
P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );
P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );
P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );
P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );
P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );
P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );
P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );
P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );
P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );
P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );
P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );
P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );
P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );
P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );
P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );
P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );
P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );
P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );
P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );
P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );
P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );
P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );
P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );
P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );
P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );
P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );
P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );
P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );
P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );
P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );
P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );
P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );
P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );
P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );
P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );
P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );
P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );
P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );
P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );
P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );
P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );
P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );
P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );
P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );
P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );
P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );
P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
/*
* SHA-256 process buffer
*/
void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen )
{
size_t fill;
uint32_t left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
sha2_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
sha2_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha2_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-256 final digest
*/
void sha2_finish( sha2_context *ctx, unsigned char output[32] )
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
sha2_update( ctx, sha2_padding, padn );
sha2_update( ctx, msglen, 8 );
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
PUT_UINT32_BE( ctx->state[3], output, 12 );
PUT_UINT32_BE( ctx->state[4], output, 16 );
PUT_UINT32_BE( ctx->state[5], output, 20 );
PUT_UINT32_BE( ctx->state[6], output, 24 );
if( ctx->is224 == 0 )
PUT_UINT32_BE( ctx->state[7], output, 28 );
}
#endif /* !POLARSSL_SHA2_ALT */
/*
* output = SHA-256( input buffer )
*/
void sha2( const unsigned char *input, size_t ilen,
unsigned char output[32], int is224 )
{
sha2_context ctx;
sha2_starts( &ctx, is224 );
sha2_update( &ctx, input, ilen );
sha2_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha2_context ) );
}
#if defined(POLARSSL_FS_IO)
/*
* output = SHA-256( file contents )
*/
int sha2_file( const char *path, unsigned char output[32], int is224 )
{
FILE *f;
size_t n;
sha2_context ctx;
unsigned char buf[1024];
if( ( f = fopen( path, "rb" ) ) == NULL )
return( POLARSSL_ERR_SHA2_FILE_IO_ERROR );
sha2_starts( &ctx, is224 );
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
sha2_update( &ctx, buf, n );
sha2_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha2_context ) );
if( ferror( f ) != 0 )
{
fclose( f );
return( POLARSSL_ERR_SHA2_FILE_IO_ERROR );
}
fclose( f );
return( 0 );
}
#endif /* POLARSSL_FS_IO */
/*
* SHA-256 HMAC context setup
*/
void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen,
int is224 )
{
size_t i;
unsigned char sum[32];
if( keylen > 64 )
{
sha2( key, keylen, sum, is224 );
keylen = ( is224 ) ? 28 : 32;
key = sum;
}
memset( ctx->ipad, 0x36, 64 );
memset( ctx->opad, 0x5C, 64 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
sha2_starts( ctx, is224 );
sha2_update( ctx, ctx->ipad, 64 );
memset( sum, 0, sizeof( sum ) );
}
/*
* SHA-256 HMAC process buffer
*/
void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen )
{
sha2_update( ctx, input, ilen );
}
/*
* SHA-256 HMAC final digest
*/
void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] )
{
int is224, hlen;
unsigned char tmpbuf[32];
is224 = ctx->is224;
hlen = ( is224 == 0 ) ? 32 : 28;
sha2_finish( ctx, tmpbuf );
sha2_starts( ctx, is224 );
sha2_update( ctx, ctx->opad, 64 );
sha2_update( ctx, tmpbuf, hlen );
sha2_finish( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* SHA-256 HMAC context reset
*/
void sha2_hmac_reset( sha2_context *ctx )
{
sha2_starts( ctx, ctx->is224 );
sha2_update( ctx, ctx->ipad, 64 );
}
/*
* output = HMAC-SHA-256( hmac key, input buffer )
*/
void sha2_hmac( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char output[32], int is224 )
{
sha2_context ctx;
sha2_hmac_starts( &ctx, key, keylen, is224 );
sha2_hmac_update( &ctx, input, ilen );
sha2_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha2_context ) );
}
#if defined(POLARSSL_SELF_TEST)
/*
* FIPS-180-2 test vectors
*/
static unsigned char sha2_test_buf[3][57] =
{
{ "abc" },
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
{ "" }
};
static const int sha2_test_buflen[3] =
{
3, 56, 1000
};
static const unsigned char sha2_test_sum[6][32] =
{
/*
* SHA-224 test vectors
*/
{ 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
0xE3, 0x6C, 0x9D, 0xA7 },
{ 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
0x52, 0x52, 0x25, 0x25 },
{ 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
0x4E, 0xE7, 0xAD, 0x67 },
/*
* SHA-256 test vectors
*/
{ 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
{ 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
{ 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
};
/*
* RFC 4231 test vectors
*/
static unsigned char sha2_hmac_test_key[7][26] =
{
{ "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
"\x0B\x0B\x0B\x0B" },
{ "Jefe" },
{ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
"\xAA\xAA\xAA\xAA" },
{ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
{ "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
"\x0C\x0C\x0C\x0C" },
{ "" }, /* 0xAA 131 times */
{ "" }
};
static const int sha2_hmac_test_keylen[7] =
{
20, 4, 20, 25, 20, 131, 131
};
static unsigned char sha2_hmac_test_buf[7][153] =
{
{ "Hi There" },
{ "what do ya want for nothing?" },
{ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
{ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
{ "Test With Truncation" },
{ "Test Using Larger Than Block-Size Key - Hash Key First" },
{ "This is a test using a larger than block-size key "
"and a larger than block-size data. The key needs to "
"be hashed before being used by the HMAC algorithm." }
};
static const int sha2_hmac_test_buflen[7] =
{
8, 28, 50, 50, 20, 54, 152
};
static const unsigned char sha2_hmac_test_sum[14][32] =
{
/*
* HMAC-SHA-224 test vectors
*/
{ 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19,
0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F,
0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F,
0x53, 0x68, 0x4B, 0x22 },
{ 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF,
0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F,
0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00,
0x8F, 0xD0, 0x5E, 0x44 },
{ 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6,
0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64,
0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1,
0xEC, 0x83, 0x33, 0xEA },
{ 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC,
0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C,
0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D,
0xE7, 0xAF, 0xEC, 0x5A },
{ 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37,
0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 },
{ 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD,
0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2,
0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27,
0x3F, 0xA6, 0x87, 0x0E },
{ 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02,
0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD,
0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9,
0xF6, 0xF5, 0x65, 0xD1 },
/*
* HMAC-SHA-256 test vectors
*/
{ 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53,
0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B,
0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7,
0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 },
{ 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E,
0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7,
0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83,
0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 },
{ 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46,
0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7,
0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22,
0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE },
{ 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E,
0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A,
0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07,
0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B },
{ 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0,
0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B },
{ 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F,
0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F,
0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14,
0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 },
{ 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB,
0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44,
0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93,
0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 }
};
/*
* Checkup routine
*/
int sha2_self_test( int verbose )
{
int i, j, k, buflen;
unsigned char buf[1024];
unsigned char sha2sum[32];
sha2_context ctx;
for( i = 0; i < 6; i++ )
{
j = i % 3;
k = i < 3;
if( verbose != 0 )
printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 );
sha2_starts( &ctx, k );
if( j == 2 )
{
memset( buf, 'a', buflen = 1000 );
for( j = 0; j < 1000; j++ )
sha2_update( &ctx, buf, buflen );
}
else
sha2_update( &ctx, sha2_test_buf[j],
sha2_test_buflen[j] );
sha2_finish( &ctx, sha2sum );
if( memcmp( sha2sum, sha2_test_sum[i], 32 - k * 4 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
for( i = 0; i < 14; i++ )
{
j = i % 7;
k = i < 7;
if( verbose != 0 )
printf( " HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 );
if( j == 5 || j == 6 )
{
memset( buf, '\xAA', buflen = 131 );
sha2_hmac_starts( &ctx, buf, buflen, k );
}
else
sha2_hmac_starts( &ctx, sha2_hmac_test_key[j],
sha2_hmac_test_keylen[j], k );
sha2_hmac_update( &ctx, sha2_hmac_test_buf[j],
sha2_hmac_test_buflen[j] );
sha2_hmac_finish( &ctx, sha2sum );
buflen = ( j == 4 ) ? 16 : 32 - k * 4;
if( memcmp( sha2sum, sha2_hmac_test_sum[i], buflen ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
return( 0 );
}
#endif
#endif
+183
View File
@@ -0,0 +1,183 @@
/**
* \file sha2.h
*
* \brief SHA-224 and SHA-256 cryptographic hash function
*
* Copyright (C) 2006-2013, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_SHA2_H
#define POLARSSL_SHA2_H
#include "polarssl/config.h"
#include <string.h>
#ifdef _MSC_VER
#include <basetsd.h>
typedef UINT32 uint32_t;
#else
#include <inttypes.h>
#endif
#define POLARSSL_ERR_SHA2_FILE_IO_ERROR -0x0078 /**< Read/write error in file. */
// Regular implementation
//
/**
* \brief SHA-256 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[8]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
unsigned char ipad[64]; /*!< HMAC: inner padding */
unsigned char opad[64]; /*!< HMAC: outer padding */
int is224; /*!< 0 => SHA-256, else SHA-224 */
}
sha2_context;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-256 context setup
*
* \param ctx context to be initialized
* \param is224 0 = use SHA256, 1 = use SHA224
*/
void sha2_starts( sha2_context *ctx, int is224 );
/**
* \brief SHA-256 process buffer
*
* \param ctx SHA-256 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-256 final digest
*
* \param ctx SHA-256 context
* \param output SHA-224/256 checksum result
*/
void sha2_finish( sha2_context *ctx, unsigned char output[32] );
/* Internal use */
void sha2_process( sha2_context *ctx, const unsigned char data[64] );
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Output = SHA-256( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-224/256 checksum result
* \param is224 0 = use SHA256, 1 = use SHA224
*/
void sha2( const unsigned char *input, size_t ilen,
unsigned char output[32], int is224 );
/**
* \brief Output = SHA-256( file contents )
*
* \param path input file name
* \param output SHA-224/256 checksum result
* \param is224 0 = use SHA256, 1 = use SHA224
*
* \return 0 if successful, or POLARSSL_ERR_SHA2_FILE_IO_ERROR
*/
int sha2_file( const char *path, unsigned char output[32], int is224 );
/**
* \brief SHA-256 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param is224 0 = use SHA256, 1 = use SHA224
*/
void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen,
int is224 );
/**
* \brief SHA-256 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-256 HMAC final digest
*
* \param ctx HMAC context
* \param output SHA-224/256 HMAC checksum result
*/
void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] );
/**
* \brief SHA-256 HMAC context reset
*
* \param ctx HMAC context to be reset
*/
void sha2_hmac_reset( sha2_context *ctx );
/**
* \brief Output = HMAC-SHA-256( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-SHA-224/256 result
* \param is224 0 = use SHA256, 1 = use SHA224
*/
void sha2_hmac( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char output[32], int is224 );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int sha2_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* sha2.h */