1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-04-11 16:18:06 -05:00

Rewrite the testcrypt.c macro system.

Yesterday's commit 52ee636b092c199 which further extended the huge
pile of arity-specific annoying wrapper macros pushed me over the edge
and inspired me to give some harder thought to finding a way to handle
all arities at once. And this time I found one!

The new technique changes the syntax of the function specifications in
testcrypt.h. In particular, they now have to specify a _name_ for each
parameter as well as a type, because the macros generating the C
marshalling wrappers will need a structure field for each parameter
and cpp isn't flexible enough to generate names for those fields
automatically. Rather than tediously name them arg1, arg2 etc, I've
reused the names of the parameters from the prototypes or definitions
of the underlying real functions (via a one-off auto-extraction
process starting from the output of 'clang -Xclang -dump-ast' plus
some manual polishing), which means testcrypt.h is now a bit more
self-documenting.

The testcrypt.py end of the mechanism is rewritten to eat the new
format. Since it's got more complicated syntax and nested parens and
things, I've written something a bit like a separated lexer/parser
system in place of the previous crude regex matcher, which should
enforce that the whole header file really does conform to the
restricted syntax it has to fit into.

The new system uses a lot less code in testcrypt.c, but I've made up
for that by also writing a long comment explaining how it works, which
was another thing the previous system lacked! Similarly, the new
testcrypt.h has some long-overdue instructions at the top.
This commit is contained in:
Simon Tatham 2021-11-21 10:27:30 +00:00
parent 1847ab282d
commit 3743859f97
3 changed files with 643 additions and 470 deletions

View File

@ -3,6 +3,7 @@ import os
import numbers
import subprocess
import re
import string
import struct
from binascii import hexlify
@ -269,10 +270,95 @@ class Function(object):
return retvals[0]
return tuple(retvals)
def _setup(scope):
header_file = os.path.join(putty_srcdir, "testcrypt.h")
def _lex_testcrypt_header(header):
pat = re.compile(
# Skip any combination of whitespace and comments
'(?:{})*'.format('|'.join((
'[ \t\n]', # whitespace
'/\\*(?:.|\n)*?\\*/', # C90-style /* ... */ comment, ended eagerly
'//[^\n]*\n', # C99-style comment to end-of-line
))) +
# And then match a token
'({})'.format('|'.join((
# Punctuation
'\(',
'\)',
',',
# Identifier
'[A-Za-z_][A-Za-z0-9_]*',
# End of string
'$',
)))
)
linere = re.compile(r'^FUNC\d+\((.*)\)$')
pos = 0
end = len(header)
while pos < end:
m = pat.match(header, pos)
assert m is not None, (
"Failed to lex testcrypt.h at byte position {:d}".format(pos))
pos = m.end()
tok = m.group(1)
if len(tok) == 0:
assert pos == end, (
"Empty token should only be returned at end of string")
yield tok, m.start(1)
def _parse_testcrypt_header(tokens):
def is_id(tok):
return tok[0] in string.ascii_letters+"_"
def expect(what, why, eof_ok=False):
tok, pos = next(tokens)
if tok == '' and eof_ok:
return None
if hasattr(what, '__call__'):
description = lambda: ""
ok = what(tok)
elif isinstance(what, set):
description = lambda: " or ".join("'"+x+"' " for x in sorted(what))
ok = tok in what
else:
description = lambda: "'"+what+"' "
ok = tok == what
if not ok:
sys.exit("testcrypt.h:{:d}: expected {}{}".format(
pos, description(), why))
return tok
while True:
tok = expect("FUNC", "at start of function specification", eof_ok=True)
if tok is None:
break
expect("(", "after FUNC")
rettype = expect(is_id, "return type")
expect(",", "after return type")
funcname = expect(is_id, "function name")
expect(",", "after function name")
expect("(", "to begin argument list")
args = []
firstargkind = expect({"ARG", "VOID"}, "at start of argument list")
if firstargkind == "VOID":
expect(")", "after VOID")
else:
while True:
# Every time we come back to the top of this loop, we've
# just seen 'ARG'
expect("(", "after ARG")
argtype = expect(is_id, "argument type")
expect(",", "after argument type")
argname = expect(is_id, "argument name")
args.append((argtype, argname))
expect(")", "at end of ARG")
punct = expect({",", ")"}, "after argument")
if punct == ")":
break
expect("ARG", "to begin next argument")
expect(")", "at end of FUNC")
yield funcname, rettype, args
def _setup(scope):
valprefix = "val_"
outprefix = "out_"
optprefix = "opt_"
@ -288,36 +374,34 @@ def _setup(scope):
arg = arg[:arg.index("_", len(valprefix))]
return arg
with open(header_file) as f:
for line in iter(f.readline, ""):
line = line.rstrip("\r\n").replace(" ", "")
m = linere.match(line)
if m is not None:
words = m.group(1).split(",")
function = words[1]
rettypes = []
argtypes = []
argsconsumed = []
if words[0] != "void":
rettypes.append(trim_argtype(words[0]))
for arg in words[2:]:
if arg.startswith(outprefix):
rettypes.append(trim_argtype(arg[len(outprefix):]))
else:
consumed = False
if arg.startswith(consprefix):
arg = arg[len(consprefix):]
consumed = True
arg = trim_argtype(arg)
argtypes.append((arg, consumed))
func = Function(function, rettypes, argtypes)
scope[function] = func
if len(argtypes) > 0:
t = argtypes[0][0]
if (t in method_prefixes and
function.startswith(method_prefixes[t])):
methodname = function[len(method_prefixes[t]):]
method_lists[t].append((methodname, func))
with open(os.path.join(putty_srcdir, "testcrypt.h")) as f:
header = f.read()
tokens = _lex_testcrypt_header(header)
for function, rettype, arglist in _parse_testcrypt_header(tokens):
rettypes = []
if rettype != "void":
rettypes.append(trim_argtype(rettype))
argtypes = []
argsconsumed = []
for arg, argname in arglist:
if arg.startswith(outprefix):
rettypes.append(trim_argtype(arg[len(outprefix):]))
else:
consumed = False
if arg.startswith(consprefix):
arg = arg[len(consprefix):]
consumed = True
arg = trim_argtype(arg)
argtypes.append((arg, consumed))
func = Function(function, rettypes, argtypes)
scope[function] = func
if len(argtypes) > 0:
t = argtypes[0][0]
if (t in method_prefixes and
function.startswith(method_prefixes[t])):
methodname = function[len(method_prefixes[t]):]
method_lists[t].append((methodname, func))
_setup(globals())
del _setup

View File

@ -1406,180 +1406,226 @@ typedef Argon2Flavour TD_argon2flavour;
typedef FingerprintType TD_fptype;
typedef HttpDigestHash TD_httpdigesthash;
#define FUNC0(rettype, function) \
static void handle_##function(BinarySource *in, strbuf *out) { \
return_##rettype(out, function()); \
}
/*
* HERE BE DRAGONS: the horrible C preprocessor business that reads
* testcrypt.h and generates a marshalling wrapper for each exported
* function.
*
* In an ideal world, we would start from a specification like this in
* testcrypt.h
*
* FUNC(val_foo, example, (ARG(val_bar, bar), ARG(uint, n)))
*
* and generate a wrapper function looking like this:
*
* static void handle_example(BinarySource *in, strbuf *out) {
* TD_val_bar bar = get_val_bar(in);
* TD_uint n = get_uint(in);
* return_val_foo(out, example(bar, n));
* }
*
* which would read the marshalled form of each function argument in
* turn from the input BinarySource via the get_<type>() function
* family defined in this file; assign each argument to a local
* variable; call the underlying C function with all those arguments;
* and then call a function of the return_<type>() family to marshal
* the output value into the output strbuf to be sent to standard
* output.
*
* With a more general macro processor such as m4, or custom code in
* Perl or Python, or a helper program like llvm-tblgen, we could just
* do that directly, reading function specifications from testcrypt.h
* and writing out exactly the above. But we don't have a fully
* general macro processor (since everything in that category
* introduces an extra build dependency that's awkward on plain
* Windows, or requires compiling and running a helper program which
* is awkward in a cross-compile). We only have cpp. And in cpp, a
* macro can't expand one of its arguments differently in two parts of
* its own expansion. So we have to be more clever.
*
* In place of the above code, I instead generate three successive
* declarations for each function. In simplified form they would look
* like this:
*
* typedef struct ARGS_example {
* TD_val_bar bar;
* TD_uint n;
* } ARGS_example;
*
* static inline ARGS_example get_args_example(BinarySource *in) {
* ARGS_example args;
* args.bar = get_val_bar(in);
* args.n = get_uint(in);
* return args;
* }
*
* static void handle_example(BinarySource *in, strbuf *out) {
* ARGS_example args = get_args_example(in);
* return_val_foo(out, example(args.bar, args.n));
* }
*
* Each of these mentions the arguments and their types just _once_,
* so each one can be generated by a single expansion of the FUNC(...)
* specification in testcrypt.h, with FUNC and ARG and VOID defined to
* appropriate values.
*
* Or ... *nearly*. In fact, I left out several details there, but
* it's a good starting point to understand the full version.
*
* To begin with, several of the variable names shown above are
* actually named with an ugly leading underscore, to minimise the
* chance of them colliding with real parameter names. (You could
* easily imagine 'out' being the name of a parameter to one of the
* wrapped functions.) Also, we memset the whole structure to zero at
* the start of get_args_example() to avoid compiler warnings about
* uninitialised stuff, and insert a precautionary '(void)args;' in
* handle_example to avoid a similar warning about _unused_ stuff.
*
* The big problem is the commas that have to appear between arguments
* in the final call to the actual C function. Those can't be
* generated by expanding the ARG macro itself, or you'd get one too
* many - either a leading comma or a trailing comma. Trailing commas
* are legal in a Python function call, but unfortunately C is not yet
* so enlightened. (C permits a trailing comma in a struct or array
* initialiser, and is coming round to it in enums, but hasn't yet
* seen the light about function calls or function prototypes.)
*
* So the commas must appear _between_ ARG(...) specifiers. And that
* means they unavoidably appear in _every_ expansion of FUNC() (or
* rather, every expansion that uses the argument list at all).
* Therefore, we need to ensure they're harmless in the other two
* functions as well.
*
* In the get_args_example() function above, there's no real problem.
* The list of assignments can perfectly well be separated by commas
* instead of semicolons, so that it becomes a single expression-
* statement instead of a sequence of them; the comma operator still
* defines a sequence point, so it's fine.
*
* But what about the structure definition of ARGS_example?
*
* To get round that, we fill the structure with pointless extra
* cruft, in the form of an extra 'int' field before and after each
* actually useful argument field. So the real structure definition
* ends up looking more like this:
*
* typedef struct ARGS_example {
* int _predummy_bar;
* TD_val_bar bar;
* int _postdummy_bar, _predummy_n;
* TD_uint n;
* int _postdummy_n;
* } ARGS_example;
*
* Those extra 'int' fields are ignored completely at run time. They
* might cause a runtime space cost if the struct doesn't get
* completely optimised away when get_args_example is inlined into
* handle_example, but even if so, that's OK, this is a test program
* whose memory usage isn't critical. The real point is that, in
* between each pair of real arguments, there's a declaration
* containing *two* int variables, and in between them is the vital
* comma that we need!
*
* So in that pass through testcrypt.h, the ARG(type, name) macro has
* to expand to the weird piece of text
*
* _predummy_name; // terminating the previous int declaration
* TD_type name; // declaring the thing we actually wanted
* int _postdummy_name // new declaration ready to see a comma
*
* so that a comma-separated list of pieces of expansion like that
* will fall into just the right form to be the core of the above
* expanded structure definition. Then we just need to put in the
* 'int' after the open brace, and the ';' before the closing brace,
* and we've got everything we need to make it all syntactically legal.
*
* Other points of note:
*
* Why the extra pair of parens around the whole argument list? You'd
* like to think that FUNC could be a variadic macro, and just use
* __VA_ARGS__ to expand all the arguments wherever they're needed.
* But unfortunately there's a portability consideration: some of the
* 'functions' wrapped by this system are actually macros in turn, and
* if you use __VA_ARGS__ to expand multiple arguments from one macro
* into the argument list of another macro, compilers disagree on what
* happens: Visual Studio in particular will turn __VA_ARGS__ into
* just one argument instead of multiple ones. That is, if you do this:
*
* #define DESTINATION_MACRO(a, b) ... stuff using a and b ...
* #define WRAPPER(...) DESTINATION_MACRO(__VA_ARGS__)
* WRAPPER(1, 2)
*
* then most compilers will behave as if you'd called
* DESTINATION_MACRO with 'a' expanding to 1 and 'b' expanding to 2.
* But Visual Studio will consider that you called it with 'a'
* expanding to the whole of __VA_ARGS__ - that is, the token sequence
* '1 , 2' - and will expand 'b' to nothing at all!
*
* So we have a constraint that if ARGS is going to be turned into the
* argument list to the actual called function - as it is in the final
* handle_example() expansion shown above - then the commas can't come
* from a variadic expansion of __VA_ARGS__. Hence, FUNC can't _be_ a
* variadic macro. Instead, we wrap all the arguments in an extra pair
* of parens, and generate the final call not by saying function(args)
* but by saying just 'function args', since 'args' contains the
* parens already.
*
* In get_args_example(), that's still fine, because our giant
* comma-separated expression containing multiple assignment
* subexpressions can legally be wrapped in parentheses as well. But
* what do you do in the structure definition?
*
* Answer: _there_ we use a variadic macro to strip off the outer
* parens, by expanding to just __VA_ARGS__. That's OK even in Visual
* Studio, because in this particular context, __VA_ARGS__ is ending
* up in a structure definition and definitely _not_ in the argument
* list of another macro.
*
* Finally, what if a wrapped function has _no_ arguments? Two out of
* three uses of the argument list here need some kind of special case
* for that. That's why you have to write 'VOID' explicitly in an
* empty argument list in testcrypt.h: we make VOID expand to whatever
* is needed to avoid a syntax error in that special case.
*/
#define FUNC1(rettype, function, type1) \
static void handle_##function(BinarySource *in, strbuf *out) { \
TD_##type1 arg1 = get_##type1(in); \
return_##rettype(out, function(arg1)); \
}
#define FUNC2(rettype, function, type1, type2) \
static void handle_##function(BinarySource *in, strbuf *out) { \
TD_##type1 arg1 = get_##type1(in); \
TD_##type2 arg2 = get_##type2(in); \
return_##rettype(out, function(arg1, arg2)); \
}
#define FUNC3(rettype, function, type1, type2, type3) \
static void handle_##function(BinarySource *in, strbuf *out) { \
TD_##type1 arg1 = get_##type1(in); \
TD_##type2 arg2 = get_##type2(in); \
TD_##type3 arg3 = get_##type3(in); \
return_##rettype(out, function(arg1, arg2, arg3)); \
}
#define FUNC4(rettype, function, type1, type2, type3, type4) \
static void handle_##function(BinarySource *in, strbuf *out) { \
TD_##type1 arg1 = get_##type1(in); \
TD_##type2 arg2 = get_##type2(in); \
TD_##type3 arg3 = get_##type3(in); \
TD_##type4 arg4 = get_##type4(in); \
return_##rettype(out, function(arg1, arg2, arg3, arg4)); \
}
#define FUNC5(rettype, function, type1, type2, type3, type4, type5) \
static void handle_##function(BinarySource *in, strbuf *out) { \
TD_##type1 arg1 = get_##type1(in); \
TD_##type2 arg2 = get_##type2(in); \
TD_##type3 arg3 = get_##type3(in); \
TD_##type4 arg4 = get_##type4(in); \
TD_##type5 arg5 = get_##type5(in); \
return_##rettype(out, function(arg1, arg2, arg3, arg4, arg5)); \
}
#define FUNC6(rettype, function, type1, type2, type3, type4, type5, \
type6) \
static void handle_##function(BinarySource *in, strbuf *out) { \
TD_##type1 arg1 = get_##type1(in); \
TD_##type2 arg2 = get_##type2(in); \
TD_##type3 arg3 = get_##type3(in); \
TD_##type4 arg4 = get_##type4(in); \
TD_##type5 arg5 = get_##type5(in); \
TD_##type6 arg6 = get_##type6(in); \
return_##rettype(out, function(arg1, arg2, arg3, arg4, arg5, \
arg6)); \
}
#define FUNC7(rettype, function, type1, type2, type3, type4, type5, \
type6, type7) \
static void handle_##function(BinarySource *in, strbuf *out) { \
TD_##type1 arg1 = get_##type1(in); \
TD_##type2 arg2 = get_##type2(in); \
TD_##type3 arg3 = get_##type3(in); \
TD_##type4 arg4 = get_##type4(in); \
TD_##type5 arg5 = get_##type5(in); \
TD_##type6 arg6 = get_##type6(in); \
TD_##type7 arg7 = get_##type7(in); \
return_##rettype(out, function(arg1, arg2, arg3, arg4, arg5, \
arg6, arg7)); \
}
#define FUNC8(rettype, function, type1, type2, type3, type4, type5, \
type6, type7, type8) \
static void handle_##function(BinarySource *in, strbuf *out) { \
TD_##type1 arg1 = get_##type1(in); \
TD_##type2 arg2 = get_##type2(in); \
TD_##type3 arg3 = get_##type3(in); \
TD_##type4 arg4 = get_##type4(in); \
TD_##type5 arg5 = get_##type5(in); \
TD_##type6 arg6 = get_##type6(in); \
TD_##type7 arg7 = get_##type7(in); \
TD_##type8 arg8 = get_##type8(in); \
return_##rettype(out, function(arg1, arg2, arg3, arg4, arg5, \
arg6, arg7, arg8)); \
}
#define FUNC9(rettype, function, type1, type2, type3, type4, type5, \
type6, type7, type8, type9) \
static void handle_##function(BinarySource *in, strbuf *out) { \
TD_##type1 arg1 = get_##type1(in); \
TD_##type2 arg2 = get_##type2(in); \
TD_##type3 arg3 = get_##type3(in); \
TD_##type4 arg4 = get_##type4(in); \
TD_##type5 arg5 = get_##type5(in); \
TD_##type6 arg6 = get_##type6(in); \
TD_##type7 arg7 = get_##type7(in); \
TD_##type8 arg8 = get_##type8(in); \
TD_##type9 arg9 = get_##type9(in); \
return_##rettype(out, function(arg1, arg2, arg3, arg4, arg5, \
arg6, arg7, arg8, arg9)); \
}
#define FUNC10(rettype, function, type1, type2, type3, type4, type5, \
type6, type7, type8, type9, type10) \
static void handle_##function(BinarySource *in, strbuf *out) { \
TD_##type1 arg1 = get_##type1(in); \
TD_##type2 arg2 = get_##type2(in); \
TD_##type3 arg3 = get_##type3(in); \
TD_##type4 arg4 = get_##type4(in); \
TD_##type5 arg5 = get_##type5(in); \
TD_##type6 arg6 = get_##type6(in); \
TD_##type7 arg7 = get_##type7(in); \
TD_##type8 arg8 = get_##type8(in); \
TD_##type9 arg9 = get_##type9(in); \
TD_##type10 arg10 = get_##type10(in); \
return_##rettype(out, function(arg1, arg2, arg3, arg4, arg5, \
arg6, arg7, arg8, arg9, arg10)); \
}
#define FUNC11(rettype, function, type1, type2, type3, type4, type5, \
type6, type7, type8, type9, type10, type11) \
static void handle_##function(BinarySource *in, strbuf *out) { \
TD_##type1 arg1 = get_##type1(in); \
TD_##type2 arg2 = get_##type2(in); \
TD_##type3 arg3 = get_##type3(in); \
TD_##type4 arg4 = get_##type4(in); \
TD_##type5 arg5 = get_##type5(in); \
TD_##type6 arg6 = get_##type6(in); \
TD_##type7 arg7 = get_##type7(in); \
TD_##type8 arg8 = get_##type8(in); \
TD_##type9 arg9 = get_##type9(in); \
TD_##type10 arg10 = get_##type10(in); \
TD_##type11 arg11 = get_##type11(in); \
return_##rettype(out, function(arg1, arg2, arg3, arg4, arg5, \
arg6, arg7, arg8, arg9, arg10, \
arg11)); \
}
#define FUNC12(rettype, function, type1, type2, type3, type4, type5, \
type6, type7, type8, type9, type10, type11, type12) \
static void handle_##function(BinarySource *in, strbuf *out) { \
TD_##type1 arg1 = get_##type1(in); \
TD_##type2 arg2 = get_##type2(in); \
TD_##type3 arg3 = get_##type3(in); \
TD_##type4 arg4 = get_##type4(in); \
TD_##type5 arg5 = get_##type5(in); \
TD_##type6 arg6 = get_##type6(in); \
TD_##type7 arg7 = get_##type7(in); \
TD_##type8 arg8 = get_##type8(in); \
TD_##type9 arg9 = get_##type9(in); \
TD_##type10 arg10 = get_##type10(in); \
TD_##type11 arg11 = get_##type11(in); \
TD_##type12 arg12 = get_##type12(in); \
return_##rettype(out, function(arg1, arg2, arg3, arg4, arg5, \
arg6, arg7, arg8, arg9, arg10, \
arg11, arg12)); \
}
#define DEPARENTHESISE(...) __VA_ARGS__
#define ARG(type, arg) _predummy_##arg; TD_##type arg; int _postdummy_##arg
#define VOID _voiddummy
#define FUNC(outtype, fname, args) \
typedef struct ARGS_##fname { \
int DEPARENTHESISE args; \
} ARGS_##fname;
#include "testcrypt.h"
#undef FUNC
#undef ARG
#undef VOID
#undef FUNC12
#undef FUNC11
#undef FUNC10
#undef FUNC9
#undef FUNC8
#undef FUNC7
#undef FUNC6
#undef FUNC5
#undef FUNC4
#undef FUNC3
#undef FUNC2
#undef FUNC1
#undef FUNC0
#define ARG(type, arg) _args.arg = get_##type(_in)
#define VOID ((void)0)
#define FUNC(outtype, fname, args) \
static inline ARGS_##fname get_args_##fname(BinarySource *_in) { \
ARGS_##fname _args; \
memset(&_args, 0, sizeof(_args)); \
args; \
return _args; \
}
#include "testcrypt.h"
#undef FUNC
#undef ARG
#undef VOID
#define ARG(type, arg) _args.arg
#define VOID
#define FUNC(outtype, fname, args) \
static void handle_##fname(BinarySource *_in, strbuf *_out) { \
ARGS_##fname _args = get_args_##fname(_in); \
(void)_args; /* suppress warning if no actual arguments */ \
return_##outtype(_out, fname args); \
}
#include "testcrypt.h"
#undef FUNC
#undef ARG
static void process_line(BinarySource *in, strbuf *out)
{
@ -1601,35 +1647,14 @@ static void process_line(BinarySource *in, strbuf *out)
DISPATCH_COMMAND(mp_dump);
#undef DISPATCH_COMMAND
#define FUNC0(ret,fn) DISPATCH_INTERNAL(#fn,handle_##fn);
#define FUNC1(ret,fn,...) DISPATCH_INTERNAL(#fn,handle_##fn);
#define FUNC2(ret,fn,...) DISPATCH_INTERNAL(#fn,handle_##fn);
#define FUNC3(ret,fn,...) DISPATCH_INTERNAL(#fn,handle_##fn);
#define FUNC4(ret,fn,...) DISPATCH_INTERNAL(#fn,handle_##fn);
#define FUNC5(ret,fn,...) DISPATCH_INTERNAL(#fn,handle_##fn);
#define FUNC6(ret,fn,...) DISPATCH_INTERNAL(#fn,handle_##fn);
#define FUNC7(ret,fn,...) DISPATCH_INTERNAL(#fn,handle_##fn);
#define FUNC8(ret,fn,...) DISPATCH_INTERNAL(#fn,handle_##fn);
#define FUNC9(ret,fn,...) DISPATCH_INTERNAL(#fn,handle_##fn);
#define FUNC10(ret,fn,...) DISPATCH_INTERNAL(#fn,handle_##fn);
#define FUNC11(ret,fn,...) DISPATCH_INTERNAL(#fn,handle_##fn);
#define FUNC12(ret,fn,...) DISPATCH_INTERNAL(#fn,handle_##fn);
#define FUNC(outtype, fname, args) DISPATCH_INTERNAL(#fname,handle_##fname);
#define ARG1(type, arg)
#define ARGN(type, arg)
#define VOID
#include "testcrypt.h"
#undef FUNC12
#undef FUNC11
#undef FUNC10
#undef FUNC9
#undef FUNC8
#undef FUNC7
#undef FUNC6
#undef FUNC5
#undef FUNC4
#undef FUNC3
#undef FUNC2
#undef FUNC1
#undef FUNC0
#undef FUNC
#undef ARG
#undef VOID
#undef DISPATCH_INTERNAL

View File

@ -1,126 +1,190 @@
/*
* List of functions exported by the 'testcrypt' system to provide a
* Python API for running unit tests and auxiliary programs.
*
* Each function definition in this file has the form
*
* FUNC(return-type, function-name, (arguments))
*
* where 'arguments' in turn is either VOID, or a comma-separated list
* of argument specifications of the form
*
* ARG(argument-type, argument-name)
*
* Type names are always single identifiers, and they have some
* standard prefixes:
*
* 'val_' means that the type refers to something dynamically
* allocated, so that it has a persistent identity, needs to be freed
* when finished with (though this is done automatically by the
* testcrypt.py system via Python's reference counting), and may also
* be mutable. The argument type in C will be a pointer; in Python the
* corresponding argument will be an instance of a 'Value' object
* defined in testcrypt.py.
*
* 'opt_val_' is a modification of 'val_' to indicate that the pointer
* may be NULL. In Python this is translated by accepting (or
* returning) None as an alternative to a Value.
*
* 'out_' on an argument type indicates an additional output
* parameter. The argument type in C has an extra layer of
* indirection, e.g. an 'out_val_mpint' is an 'mpint **' instead of an
* 'mpint *', identifying a pointer variable where the returned
* pointer value will be written. In the Python API, these arguments
* do not appear in the argument list of the Python function; instead
* they cause the return value to become a tuple, with additional
* types appended. For example, a declaration like
*
* FUNC(val_foo, example, (ARG(out_val_bar, bar), ARG(val_baz, baz)))
*
* would identify a function in C with the following prototype, which
* returns a 'foo *' directly and a 'bar *' by writing it through the
* provided 'bar **' pointer argument:
*
* foo *example(bar **extra_output, baz *input);
*
* and in Python this would become a function taking one argument of
* type 'baz' and returning a tuple of the form (foo, bar).
*
* 'out_' and 'opt_' can go together, if a function returns a second
* output value but it may in some cases be NULL.
*
* 'consumed_' on an argument type indicates that the C function
* receiving that argument frees it as a side effect.
*
* Any argument type which does not start 'val_' is plain old data
* with no dynamic allocation requirements. Ordinary C integers are
* sometimes handled this way (e.g. 'uint'). Other plain-data types
* are represented in Python as a string that must be one of a
* recognised set of keywords; in C these variously translate into
* enumeration types (e.g. argon2flavour, rsaorder) or pointers to
* const vtables of one kind or another (e.g. keyalg, hashalg,
* primegenpolicy).
*/
/*
* mpint.h functions.
*/
FUNC1(val_mpint, mp_new, uint)
FUNC1(void, mp_clear, val_mpint)
FUNC1(val_mpint, mp_from_bytes_le, val_string_ptrlen)
FUNC1(val_mpint, mp_from_bytes_be, val_string_ptrlen)
FUNC1(val_mpint, mp_from_integer, uint)
FUNC1(val_mpint, mp_from_decimal_pl, val_string_ptrlen)
FUNC1(val_mpint, mp_from_decimal, val_string_asciz)
FUNC1(val_mpint, mp_from_hex_pl, val_string_ptrlen)
FUNC1(val_mpint, mp_from_hex, val_string_asciz)
FUNC1(val_mpint, mp_copy, val_mpint)
FUNC1(val_mpint, mp_power_2, uint)
FUNC2(uint, mp_get_byte, val_mpint, uint)
FUNC2(uint, mp_get_bit, val_mpint, uint)
FUNC3(void, mp_set_bit, val_mpint, uint, uint)
FUNC1(uint, mp_max_bytes, val_mpint)
FUNC1(uint, mp_max_bits, val_mpint)
FUNC1(uint, mp_get_nbits, val_mpint)
FUNC1(val_string_asciz, mp_get_decimal, val_mpint)
FUNC1(val_string_asciz, mp_get_hex, val_mpint)
FUNC1(val_string_asciz, mp_get_hex_uppercase, val_mpint)
FUNC2(uint, mp_cmp_hs, val_mpint, val_mpint)
FUNC2(uint, mp_cmp_eq, val_mpint, val_mpint)
FUNC2(uint, mp_hs_integer, val_mpint, uint)
FUNC2(uint, mp_eq_integer, val_mpint, uint)
FUNC3(void, mp_min_into, val_mpint, val_mpint, val_mpint)
FUNC3(void, mp_max_into, val_mpint, val_mpint, val_mpint)
FUNC2(val_mpint, mp_min, val_mpint, val_mpint)
FUNC2(val_mpint, mp_max, val_mpint, val_mpint)
FUNC2(void, mp_copy_into, val_mpint, val_mpint)
FUNC4(void, mp_select_into, val_mpint, val_mpint, val_mpint, uint)
FUNC3(void, mp_add_into, val_mpint, val_mpint, val_mpint)
FUNC3(void, mp_sub_into, val_mpint, val_mpint, val_mpint)
FUNC3(void, mp_mul_into, val_mpint, val_mpint, val_mpint)
FUNC2(val_mpint, mp_add, val_mpint, val_mpint)
FUNC2(val_mpint, mp_sub, val_mpint, val_mpint)
FUNC2(val_mpint, mp_mul, val_mpint, val_mpint)
FUNC3(void, mp_and_into, val_mpint, val_mpint, val_mpint)
FUNC3(void, mp_or_into, val_mpint, val_mpint, val_mpint)
FUNC3(void, mp_xor_into, val_mpint, val_mpint, val_mpint)
FUNC3(void, mp_bic_into, val_mpint, val_mpint, val_mpint)
FUNC2(void, mp_copy_integer_into, val_mpint, uint)
FUNC3(void, mp_add_integer_into, val_mpint, val_mpint, uint)
FUNC3(void, mp_sub_integer_into, val_mpint, val_mpint, uint)
FUNC3(void, mp_mul_integer_into, val_mpint, val_mpint, uint)
FUNC4(void, mp_cond_add_into, val_mpint, val_mpint, val_mpint, uint)
FUNC4(void, mp_cond_sub_into, val_mpint, val_mpint, val_mpint, uint)
FUNC3(void, mp_cond_swap, val_mpint, val_mpint, uint)
FUNC2(void, mp_cond_clear, val_mpint, uint)
FUNC4(void, mp_divmod_into, val_mpint, val_mpint, opt_val_mpint, opt_val_mpint)
FUNC2(val_mpint, mp_div, val_mpint, val_mpint)
FUNC2(val_mpint, mp_mod, val_mpint, val_mpint)
FUNC3(val_mpint, mp_nthroot, val_mpint, uint, opt_val_mpint)
FUNC2(void, mp_reduce_mod_2to, val_mpint, uint)
FUNC2(val_mpint, mp_invert_mod_2to, val_mpint, uint)
FUNC2(val_mpint, mp_invert, val_mpint, val_mpint)
FUNC5(void, mp_gcd_into, val_mpint, val_mpint, opt_val_mpint, opt_val_mpint, opt_val_mpint)
FUNC2(val_mpint, mp_gcd, val_mpint, val_mpint)
FUNC2(uint, mp_coprime, val_mpint, val_mpint)
FUNC2(val_modsqrt, modsqrt_new, val_mpint, val_mpint)
FUNC(val_mpint, mp_new, (ARG(uint, maxbits)))
FUNC(void, mp_clear, (ARG(val_mpint, x)))
FUNC(val_mpint, mp_from_bytes_le, (ARG(val_string_ptrlen, bytes)))
FUNC(val_mpint, mp_from_bytes_be, (ARG(val_string_ptrlen, bytes)))
FUNC(val_mpint, mp_from_integer, (ARG(uint, n)))
FUNC(val_mpint, mp_from_decimal_pl, (ARG(val_string_ptrlen, decimal)))
FUNC(val_mpint, mp_from_decimal, (ARG(val_string_asciz, decimal)))
FUNC(val_mpint, mp_from_hex_pl, (ARG(val_string_ptrlen, hex)))
FUNC(val_mpint, mp_from_hex, (ARG(val_string_asciz, hex)))
FUNC(val_mpint, mp_copy, (ARG(val_mpint, x)))
FUNC(val_mpint, mp_power_2, (ARG(uint, power)))
FUNC(uint, mp_get_byte, (ARG(val_mpint, x), ARG(uint, byte)))
FUNC(uint, mp_get_bit, (ARG(val_mpint, x), ARG(uint, bit)))
FUNC(void, mp_set_bit, (ARG(val_mpint, x), ARG(uint, bit), ARG(uint, val)))
FUNC(uint, mp_max_bytes, (ARG(val_mpint, x)))
FUNC(uint, mp_max_bits, (ARG(val_mpint, x)))
FUNC(uint, mp_get_nbits, (ARG(val_mpint, x)))
FUNC(val_string_asciz, mp_get_decimal, (ARG(val_mpint, x)))
FUNC(val_string_asciz, mp_get_hex, (ARG(val_mpint, x)))
FUNC(val_string_asciz, mp_get_hex_uppercase, (ARG(val_mpint, x)))
FUNC(uint, mp_cmp_hs, (ARG(val_mpint, a), ARG(val_mpint, b)))
FUNC(uint, mp_cmp_eq, (ARG(val_mpint, a), ARG(val_mpint, b)))
FUNC(uint, mp_hs_integer, (ARG(val_mpint, x), ARG(uint, n)))
FUNC(uint, mp_eq_integer, (ARG(val_mpint, x), ARG(uint, n)))
FUNC(void, mp_min_into, (ARG(val_mpint, r), ARG(val_mpint, x), ARG(val_mpint, y)))
FUNC(void, mp_max_into, (ARG(val_mpint, r), ARG(val_mpint, x), ARG(val_mpint, y)))
FUNC(val_mpint, mp_min, (ARG(val_mpint, x), ARG(val_mpint, y)))
FUNC(val_mpint, mp_max, (ARG(val_mpint, x), ARG(val_mpint, y)))
FUNC(void, mp_copy_into, (ARG(val_mpint, dest), ARG(val_mpint, src)))
FUNC(void, mp_select_into, (ARG(val_mpint, dest), ARG(val_mpint, src0), ARG(val_mpint, src1), ARG(uint, choose_src1)))
FUNC(void, mp_add_into, (ARG(val_mpint, r), ARG(val_mpint, a), ARG(val_mpint, b)))
FUNC(void, mp_sub_into, (ARG(val_mpint, r), ARG(val_mpint, a), ARG(val_mpint, b)))
FUNC(void, mp_mul_into, (ARG(val_mpint, r), ARG(val_mpint, a), ARG(val_mpint, b)))
FUNC(val_mpint, mp_add, (ARG(val_mpint, x), ARG(val_mpint, y)))
FUNC(val_mpint, mp_sub, (ARG(val_mpint, x), ARG(val_mpint, y)))
FUNC(val_mpint, mp_mul, (ARG(val_mpint, x), ARG(val_mpint, y)))
FUNC(void, mp_and_into, (ARG(val_mpint, r), ARG(val_mpint, a), ARG(val_mpint, b)))
FUNC(void, mp_or_into, (ARG(val_mpint, r), ARG(val_mpint, a), ARG(val_mpint, b)))
FUNC(void, mp_xor_into, (ARG(val_mpint, r), ARG(val_mpint, a), ARG(val_mpint, b)))
FUNC(void, mp_bic_into, (ARG(val_mpint, r), ARG(val_mpint, a), ARG(val_mpint, b)))
FUNC(void, mp_copy_integer_into, (ARG(val_mpint, dest), ARG(uint, n)))
FUNC(void, mp_add_integer_into, (ARG(val_mpint, r), ARG(val_mpint, a), ARG(uint, n)))
FUNC(void, mp_sub_integer_into, (ARG(val_mpint, r), ARG(val_mpint, a), ARG(uint, n)))
FUNC(void, mp_mul_integer_into, (ARG(val_mpint, r), ARG(val_mpint, a), ARG(uint, n)))
FUNC(void, mp_cond_add_into, (ARG(val_mpint, r), ARG(val_mpint, a), ARG(val_mpint, b), ARG(uint, yes)))
FUNC(void, mp_cond_sub_into, (ARG(val_mpint, r), ARG(val_mpint, a), ARG(val_mpint, b), ARG(uint, yes)))
FUNC(void, mp_cond_swap, (ARG(val_mpint, x0), ARG(val_mpint, x1), ARG(uint, swap)))
FUNC(void, mp_cond_clear, (ARG(val_mpint, x), ARG(uint, clear)))
FUNC(void, mp_divmod_into, (ARG(val_mpint, n), ARG(val_mpint, d), ARG(opt_val_mpint, q), ARG(opt_val_mpint, r)))
FUNC(val_mpint, mp_div, (ARG(val_mpint, n), ARG(val_mpint, d)))
FUNC(val_mpint, mp_mod, (ARG(val_mpint, x), ARG(val_mpint, modulus)))
FUNC(val_mpint, mp_nthroot, (ARG(val_mpint, y), ARG(uint, n), ARG(opt_val_mpint, remainder)))
FUNC(void, mp_reduce_mod_2to, (ARG(val_mpint, x), ARG(uint, p)))
FUNC(val_mpint, mp_invert_mod_2to, (ARG(val_mpint, x), ARG(uint, p)))
FUNC(val_mpint, mp_invert, (ARG(val_mpint, x), ARG(val_mpint, modulus)))
FUNC(void, mp_gcd_into, (ARG(val_mpint, a), ARG(val_mpint, b), ARG(opt_val_mpint, gcd_out), ARG(opt_val_mpint, A_out), ARG(opt_val_mpint, B_out)))
FUNC(val_mpint, mp_gcd, (ARG(val_mpint, a), ARG(val_mpint, b)))
FUNC(uint, mp_coprime, (ARG(val_mpint, a), ARG(val_mpint, b)))
FUNC(val_modsqrt, modsqrt_new, (ARG(val_mpint, p), ARG(val_mpint, any_nonsquare_mod_p)))
/* The modsqrt functions' 'success' pointer becomes a second return value */
FUNC3(val_mpint, mp_modsqrt, val_modsqrt, val_mpint, out_uint)
FUNC1(val_monty, monty_new, val_mpint)
FUNC1(val_mpint, monty_modulus, val_monty)
FUNC1(val_mpint, monty_identity, val_monty)
FUNC3(void, monty_import_into, val_monty, val_mpint, val_mpint)
FUNC2(val_mpint, monty_import, val_monty, val_mpint)
FUNC3(void, monty_export_into, val_monty, val_mpint, val_mpint)
FUNC2(val_mpint, monty_export, val_monty, val_mpint)
FUNC4(void, monty_mul_into, val_monty, val_mpint, val_mpint, val_mpint)
FUNC3(val_mpint, monty_add, val_monty, val_mpint, val_mpint)
FUNC3(val_mpint, monty_sub, val_monty, val_mpint, val_mpint)
FUNC3(val_mpint, monty_mul, val_monty, val_mpint, val_mpint)
FUNC3(val_mpint, monty_pow, val_monty, val_mpint, val_mpint)
FUNC2(val_mpint, monty_invert, val_monty, val_mpint)
FUNC3(val_mpint, monty_modsqrt, val_modsqrt, val_mpint, out_uint)
FUNC3(val_mpint, mp_modpow, val_mpint, val_mpint, val_mpint)
FUNC3(val_mpint, mp_modmul, val_mpint, val_mpint, val_mpint)
FUNC3(val_mpint, mp_modadd, val_mpint, val_mpint, val_mpint)
FUNC3(val_mpint, mp_modsub, val_mpint, val_mpint, val_mpint)
FUNC3(void, mp_lshift_safe_into, val_mpint, val_mpint, uint)
FUNC3(void, mp_rshift_safe_into, val_mpint, val_mpint, uint)
FUNC2(val_mpint, mp_rshift_safe, val_mpint, uint)
FUNC3(void, mp_lshift_fixed_into, val_mpint, val_mpint, uint)
FUNC3(void, mp_rshift_fixed_into, val_mpint, val_mpint, uint)
FUNC2(val_mpint, mp_rshift_fixed, val_mpint, uint)
FUNC1(val_mpint, mp_random_bits, uint)
FUNC2(val_mpint, mp_random_in_range, val_mpint, val_mpint)
FUNC(val_mpint, mp_modsqrt, (ARG(val_modsqrt, sc), ARG(val_mpint, x), ARG(out_uint, success)))
FUNC(val_monty, monty_new, (ARG(val_mpint, modulus)))
FUNC(val_mpint, monty_modulus, (ARG(val_monty, mc)))
FUNC(val_mpint, monty_identity, (ARG(val_monty, mc)))
FUNC(void, monty_import_into, (ARG(val_monty, mc), ARG(val_mpint, r), ARG(val_mpint, x)))
FUNC(val_mpint, monty_import, (ARG(val_monty, mc), ARG(val_mpint, x)))
FUNC(void, monty_export_into, (ARG(val_monty, mc), ARG(val_mpint, r), ARG(val_mpint, x)))
FUNC(val_mpint, monty_export, (ARG(val_monty, mc), ARG(val_mpint, x)))
FUNC(void, monty_mul_into, (ARG(val_monty, mc), ARG(val_mpint, r), ARG(val_mpint, x), ARG(val_mpint, y)))
FUNC(val_mpint, monty_add, (ARG(val_monty, mc), ARG(val_mpint, x), ARG(val_mpint, y)))
FUNC(val_mpint, monty_sub, (ARG(val_monty, mc), ARG(val_mpint, x), ARG(val_mpint, y)))
FUNC(val_mpint, monty_mul, (ARG(val_monty, mc), ARG(val_mpint, x), ARG(val_mpint, y)))
FUNC(val_mpint, monty_pow, (ARG(val_monty, mc), ARG(val_mpint, base), ARG(val_mpint, exponent)))
FUNC(val_mpint, monty_invert, (ARG(val_monty, mc), ARG(val_mpint, x)))
FUNC(val_mpint, monty_modsqrt, (ARG(val_modsqrt, sc), ARG(val_mpint, mx), ARG(out_uint, success)))
FUNC(val_mpint, mp_modpow, (ARG(val_mpint, base), ARG(val_mpint, exponent), ARG(val_mpint, modulus)))
FUNC(val_mpint, mp_modmul, (ARG(val_mpint, x), ARG(val_mpint, y), ARG(val_mpint, modulus)))
FUNC(val_mpint, mp_modadd, (ARG(val_mpint, x), ARG(val_mpint, y), ARG(val_mpint, modulus)))
FUNC(val_mpint, mp_modsub, (ARG(val_mpint, x), ARG(val_mpint, y), ARG(val_mpint, modulus)))
FUNC(void, mp_lshift_safe_into, (ARG(val_mpint, r), ARG(val_mpint, x), ARG(uint, shift)))
FUNC(void, mp_rshift_safe_into, (ARG(val_mpint, r), ARG(val_mpint, x), ARG(uint, shift)))
FUNC(val_mpint, mp_rshift_safe, (ARG(val_mpint, x), ARG(uint, shift)))
FUNC(void, mp_lshift_fixed_into, (ARG(val_mpint, r), ARG(val_mpint, a), ARG(uint, shift)))
FUNC(void, mp_rshift_fixed_into, (ARG(val_mpint, r), ARG(val_mpint, x), ARG(uint, shift)))
FUNC(val_mpint, mp_rshift_fixed, (ARG(val_mpint, x), ARG(uint, shift)))
FUNC(val_mpint, mp_random_bits, (ARG(uint, bits)))
FUNC(val_mpint, mp_random_in_range, (ARG(val_mpint, lo), ARG(val_mpint, hi)))
/*
* ecc.h functions.
*/
FUNC4(val_wcurve, ecc_weierstrass_curve, val_mpint, val_mpint, val_mpint, opt_val_mpint)
FUNC1(val_wpoint, ecc_weierstrass_point_new_identity, val_wcurve)
FUNC3(val_wpoint, ecc_weierstrass_point_new, val_wcurve, val_mpint, val_mpint)
FUNC3(val_wpoint, ecc_weierstrass_point_new_from_x, val_wcurve, val_mpint, uint)
FUNC1(val_wpoint, ecc_weierstrass_point_copy, val_wpoint)
FUNC1(uint, ecc_weierstrass_point_valid, val_wpoint)
FUNC2(val_wpoint, ecc_weierstrass_add_general, val_wpoint, val_wpoint)
FUNC2(val_wpoint, ecc_weierstrass_add, val_wpoint, val_wpoint)
FUNC1(val_wpoint, ecc_weierstrass_double, val_wpoint)
FUNC2(val_wpoint, ecc_weierstrass_multiply, val_wpoint, val_mpint)
FUNC1(uint, ecc_weierstrass_is_identity, val_wpoint)
FUNC(val_wcurve, ecc_weierstrass_curve, (ARG(val_mpint, p), ARG(val_mpint, a), ARG(val_mpint, b), ARG(opt_val_mpint, nonsquare_mod_p)))
FUNC(val_wpoint, ecc_weierstrass_point_new_identity, (ARG(val_wcurve, curve)))
FUNC(val_wpoint, ecc_weierstrass_point_new, (ARG(val_wcurve, curve), ARG(val_mpint, x), ARG(val_mpint, y)))
FUNC(val_wpoint, ecc_weierstrass_point_new_from_x, (ARG(val_wcurve, curve), ARG(val_mpint, x), ARG(uint, desired_y_parity)))
FUNC(val_wpoint, ecc_weierstrass_point_copy, (ARG(val_wpoint, wc)))
FUNC(uint, ecc_weierstrass_point_valid, (ARG(val_wpoint, P)))
FUNC(val_wpoint, ecc_weierstrass_add_general, (ARG(val_wpoint, P), ARG(val_wpoint, Q)))
FUNC(val_wpoint, ecc_weierstrass_add, (ARG(val_wpoint, P), ARG(val_wpoint, Q)))
FUNC(val_wpoint, ecc_weierstrass_double, (ARG(val_wpoint, P)))
FUNC(val_wpoint, ecc_weierstrass_multiply, (ARG(val_wpoint, B), ARG(val_mpint, n)))
FUNC(uint, ecc_weierstrass_is_identity, (ARG(val_wpoint, wp)))
/* The output pointers in get_affine all become extra output values */
FUNC3(void, ecc_weierstrass_get_affine, val_wpoint, out_val_mpint, out_val_mpint)
FUNC3(val_mcurve, ecc_montgomery_curve, val_mpint, val_mpint, val_mpint)
FUNC2(val_mpoint, ecc_montgomery_point_new, val_mcurve, val_mpint)
FUNC1(val_mpoint, ecc_montgomery_point_copy, val_mpoint)
FUNC3(val_mpoint, ecc_montgomery_diff_add, val_mpoint, val_mpoint, val_mpoint)
FUNC1(val_mpoint, ecc_montgomery_double, val_mpoint)
FUNC2(val_mpoint, ecc_montgomery_multiply, val_mpoint, val_mpint)
FUNC2(void, ecc_montgomery_get_affine, val_mpoint, out_val_mpint)
FUNC1(boolean, ecc_montgomery_is_identity, val_mpoint)
FUNC4(val_ecurve, ecc_edwards_curve, val_mpint, val_mpint, val_mpint, opt_val_mpint)
FUNC3(val_epoint, ecc_edwards_point_new, val_ecurve, val_mpint, val_mpint)
FUNC3(val_epoint, ecc_edwards_point_new_from_y, val_ecurve, val_mpint, uint)
FUNC1(val_epoint, ecc_edwards_point_copy, val_epoint)
FUNC2(val_epoint, ecc_edwards_add, val_epoint, val_epoint)
FUNC2(val_epoint, ecc_edwards_multiply, val_epoint, val_mpint)
FUNC2(uint, ecc_edwards_eq, val_epoint, val_epoint)
FUNC3(void, ecc_edwards_get_affine, val_epoint, out_val_mpint, out_val_mpint)
FUNC(void, ecc_weierstrass_get_affine, (ARG(val_wpoint, wp), ARG(out_val_mpint, x), ARG(out_val_mpint, y)))
FUNC(val_mcurve, ecc_montgomery_curve, (ARG(val_mpint, p), ARG(val_mpint, a), ARG(val_mpint, b)))
FUNC(val_mpoint, ecc_montgomery_point_new, (ARG(val_mcurve, mc), ARG(val_mpint, x)))
FUNC(val_mpoint, ecc_montgomery_point_copy, (ARG(val_mpoint, orig)))
FUNC(val_mpoint, ecc_montgomery_diff_add, (ARG(val_mpoint, P), ARG(val_mpoint, Q), ARG(val_mpoint, PminusQ)))
FUNC(val_mpoint, ecc_montgomery_double, (ARG(val_mpoint, P)))
FUNC(val_mpoint, ecc_montgomery_multiply, (ARG(val_mpoint, B), ARG(val_mpint, n)))
FUNC(void, ecc_montgomery_get_affine, (ARG(val_mpoint, mp), ARG(out_val_mpint, x)))
FUNC(boolean, ecc_montgomery_is_identity, (ARG(val_mpoint, mp)))
FUNC(val_ecurve, ecc_edwards_curve, (ARG(val_mpint, p), ARG(val_mpint, d), ARG(val_mpint, a), ARG(opt_val_mpint, nonsquare_mod_p)))
FUNC(val_epoint, ecc_edwards_point_new, (ARG(val_ecurve, curve), ARG(val_mpint, x), ARG(val_mpint, y)))
FUNC(val_epoint, ecc_edwards_point_new_from_y, (ARG(val_ecurve, curve), ARG(val_mpint, y), ARG(uint, desired_x_parity)))
FUNC(val_epoint, ecc_edwards_point_copy, (ARG(val_epoint, ec)))
FUNC(val_epoint, ecc_edwards_add, (ARG(val_epoint, P), ARG(val_epoint, Q)))
FUNC(val_epoint, ecc_edwards_multiply, (ARG(val_epoint, B), ARG(val_mpint, n)))
FUNC(uint, ecc_edwards_eq, (ARG(val_epoint, P), ARG(val_epoint, Q)))
FUNC(void, ecc_edwards_get_affine, (ARG(val_epoint, wp), ARG(out_val_mpint, x), ARG(out_val_mpint, y)))
/*
* The ssh_hash abstraction. Note the 'consumed', indicating that
@ -129,26 +193,26 @@ FUNC3(void, ecc_edwards_get_affine, val_epoint, out_val_mpint, out_val_mpint)
* ssh_hash_update is an invention of testcrypt, handled in the real C
* API by the hash object also functioning as a BinarySink.
*/
FUNC1(opt_val_hash, ssh_hash_new, hashalg)
FUNC1(void, ssh_hash_reset, val_hash)
FUNC1(val_hash, ssh_hash_copy, val_hash)
FUNC1(val_string, ssh_hash_digest, val_hash)
FUNC1(val_string, ssh_hash_final, consumed_val_hash)
FUNC2(void, ssh_hash_update, val_hash, val_string_ptrlen)
FUNC(opt_val_hash, ssh_hash_new, (ARG(hashalg, alg)))
FUNC(void, ssh_hash_reset, (ARG(val_hash, h)))
FUNC(val_hash, ssh_hash_copy, (ARG(val_hash, orig)))
FUNC(val_string, ssh_hash_digest, (ARG(val_hash, h)))
FUNC(val_string, ssh_hash_final, (ARG(consumed_val_hash, h)))
FUNC(void, ssh_hash_update, (ARG(val_hash, h), ARG(val_string_ptrlen, pl)))
FUNC1(opt_val_hash, blake2b_new_general, uint)
FUNC(opt_val_hash, blake2b_new_general, (ARG(uint, hashlen)))
/*
* The ssh2_mac abstraction. Note the optional ssh_cipher parameter
* to ssh2_mac_new. Also, again, I've invented an ssh2_mac_update so
* you can put data into the MAC.
*/
FUNC2(val_mac, ssh2_mac_new, macalg, opt_val_cipher)
FUNC2(void, ssh2_mac_setkey, val_mac, val_string_ptrlen)
FUNC1(void, ssh2_mac_start, val_mac)
FUNC2(void, ssh2_mac_update, val_mac, val_string_ptrlen)
FUNC1(val_string, ssh2_mac_genresult, val_mac)
FUNC1(val_string_asciz_const, ssh2_mac_text_name, val_mac)
FUNC(val_mac, ssh2_mac_new, (ARG(macalg, alg), ARG(opt_val_cipher, cipher)))
FUNC(void, ssh2_mac_setkey, (ARG(val_mac, m), ARG(val_string_ptrlen, key)))
FUNC(void, ssh2_mac_start, (ARG(val_mac, m)))
FUNC(void, ssh2_mac_update, (ARG(val_mac, m), ARG(val_string_ptrlen, pl)))
FUNC(val_string, ssh2_mac_genresult, (ARG(val_mac, m)))
FUNC(val_string_asciz_const, ssh2_mac_text_name, (ARG(val_mac, m)))
/*
* The ssh_key abstraction. All the uses of BinarySink and
@ -157,174 +221,174 @@ FUNC1(val_string_asciz_const, ssh2_mac_text_name, val_mac)
* all the functions that output key and signature blobs do it by
* returning a string.
*/
FUNC2(val_key, ssh_key_new_pub, keyalg, val_string_ptrlen)
FUNC3(opt_val_key, ssh_key_new_priv, keyalg, val_string_ptrlen, val_string_ptrlen)
FUNC2(opt_val_key, ssh_key_new_priv_openssh, keyalg, val_string_binarysource)
FUNC2(opt_val_string_asciz, ssh_key_invalid, val_key, uint)
FUNC4(void, ssh_key_sign, val_key, val_string_ptrlen, uint, out_val_string_binarysink)
FUNC3(boolean, ssh_key_verify, val_key, val_string_ptrlen, val_string_ptrlen)
FUNC2(void, ssh_key_public_blob, val_key, out_val_string_binarysink)
FUNC2(void, ssh_key_private_blob, val_key, out_val_string_binarysink)
FUNC2(void, ssh_key_openssh_blob, val_key, out_val_string_binarysink)
FUNC1(val_string_asciz, ssh_key_cache_str, val_key)
FUNC1(val_keycomponents, ssh_key_components, val_key)
FUNC2(uint, ssh_key_public_bits, keyalg, val_string_ptrlen)
FUNC(val_key, ssh_key_new_pub, (ARG(keyalg, self), ARG(val_string_ptrlen, pub)))
FUNC(opt_val_key, ssh_key_new_priv, (ARG(keyalg, self), ARG(val_string_ptrlen, pub), ARG(val_string_ptrlen, priv)))
FUNC(opt_val_key, ssh_key_new_priv_openssh, (ARG(keyalg, self), ARG(val_string_binarysource, src)))
FUNC(opt_val_string_asciz, ssh_key_invalid, (ARG(val_key, key), ARG(uint, flags)))
FUNC(void, ssh_key_sign, (ARG(val_key, key), ARG(val_string_ptrlen, data), ARG(uint, flags), ARG(out_val_string_binarysink, bs)))
FUNC(boolean, ssh_key_verify, (ARG(val_key, key), ARG(val_string_ptrlen, sig), ARG(val_string_ptrlen, data)))
FUNC(void, ssh_key_public_blob, (ARG(val_key, key), ARG(out_val_string_binarysink, bs)))
FUNC(void, ssh_key_private_blob, (ARG(val_key, key), ARG(out_val_string_binarysink, bs)))
FUNC(void, ssh_key_openssh_blob, (ARG(val_key, key), ARG(out_val_string_binarysink, bs)))
FUNC(val_string_asciz, ssh_key_cache_str, (ARG(val_key, key)))
FUNC(val_keycomponents, ssh_key_components, (ARG(val_key, key)))
FUNC(uint, ssh_key_public_bits, (ARG(keyalg, self), ARG(val_string_ptrlen, blob)))
/*
* Accessors to retrieve the innards of a 'key_components'.
*/
FUNC1(uint, key_components_count, val_keycomponents)
FUNC2(opt_val_string_asciz_const, key_components_nth_name, val_keycomponents, uint)
FUNC2(opt_val_string_asciz_const, key_components_nth_str, val_keycomponents, uint)
FUNC2(opt_val_mpint, key_components_nth_mp, val_keycomponents, uint)
FUNC(uint, key_components_count, (ARG(val_keycomponents, kc)))
FUNC(opt_val_string_asciz_const, key_components_nth_name, (ARG(val_keycomponents, kc), ARG(uint, n)))
FUNC(opt_val_string_asciz_const, key_components_nth_str, (ARG(val_keycomponents, kc), ARG(uint, n)))
FUNC(opt_val_mpint, key_components_nth_mp, (ARG(val_keycomponents, kc), ARG(uint, n)))
/*
* The ssh_cipher abstraction. The in-place encrypt and decrypt
* functions are wrapped to replace them with versions that take one
* string and return a separate string.
*/
FUNC1(opt_val_cipher, ssh_cipher_new, cipheralg)
FUNC2(void, ssh_cipher_setiv, val_cipher, val_string_ptrlen)
FUNC2(void, ssh_cipher_setkey, val_cipher, val_string_ptrlen)
FUNC2(val_string, ssh_cipher_encrypt, val_cipher, val_string_ptrlen)
FUNC2(val_string, ssh_cipher_decrypt, val_cipher, val_string_ptrlen)
FUNC3(val_string, ssh_cipher_encrypt_length, val_cipher, val_string_ptrlen, uint)
FUNC3(val_string, ssh_cipher_decrypt_length, val_cipher, val_string_ptrlen, uint)
FUNC(opt_val_cipher, ssh_cipher_new, (ARG(cipheralg, alg)))
FUNC(void, ssh_cipher_setiv, (ARG(val_cipher, c), ARG(val_string_ptrlen, iv)))
FUNC(void, ssh_cipher_setkey, (ARG(val_cipher, c), ARG(val_string_ptrlen, key)))
FUNC(val_string, ssh_cipher_encrypt, (ARG(val_cipher, c), ARG(val_string_ptrlen, blk)))
FUNC(val_string, ssh_cipher_decrypt, (ARG(val_cipher, c), ARG(val_string_ptrlen, blk)))
FUNC(val_string, ssh_cipher_encrypt_length, (ARG(val_cipher, c), ARG(val_string_ptrlen, blk), ARG(uint, seq)))
FUNC(val_string, ssh_cipher_decrypt_length, (ARG(val_cipher, c), ARG(val_string_ptrlen, blk), ARG(uint, seq)))
/*
* Integer Diffie-Hellman.
*/
FUNC1(val_dh, dh_setup_group, dh_group)
FUNC2(val_dh, dh_setup_gex, val_mpint, val_mpint)
FUNC1(uint, dh_modulus_bit_size, val_dh)
FUNC2(val_mpint, dh_create_e, val_dh, uint)
FUNC2(boolean, dh_validate_f, val_dh, val_mpint)
FUNC2(val_mpint, dh_find_K, val_dh, val_mpint)
FUNC(val_dh, dh_setup_group, (ARG(dh_group, kex)))
FUNC(val_dh, dh_setup_gex, (ARG(val_mpint, pval), ARG(val_mpint, gval)))
FUNC(uint, dh_modulus_bit_size, (ARG(val_dh, ctx)))
FUNC(val_mpint, dh_create_e, (ARG(val_dh, ctx), ARG(uint, nbits)))
FUNC(boolean, dh_validate_f, (ARG(val_dh, ctx), ARG(val_mpint, f)))
FUNC(val_mpint, dh_find_K, (ARG(val_dh, ctx), ARG(val_mpint, f)))
/*
* Elliptic-curve Diffie-Hellman.
*/
FUNC1(val_ecdh, ssh_ecdhkex_newkey, ecdh_alg)
FUNC2(void, ssh_ecdhkex_getpublic, val_ecdh, out_val_string_binarysink)
FUNC2(opt_val_mpint, ssh_ecdhkex_getkey, val_ecdh, val_string_ptrlen)
FUNC(val_ecdh, ssh_ecdhkex_newkey, (ARG(ecdh_alg, kex)))
FUNC(void, ssh_ecdhkex_getpublic, (ARG(val_ecdh, key), ARG(out_val_string_binarysink, bs)))
FUNC(opt_val_mpint, ssh_ecdhkex_getkey, (ARG(val_ecdh, key), ARG(val_string_ptrlen, remoteKey)))
/*
* RSA key exchange, and also the BinarySource get function
* get_ssh1_rsa_priv_agent, which is a convenient way to make an
* RSAKey for RSA kex testing purposes.
*/
FUNC1(val_rsakex, ssh_rsakex_newkey, val_string_ptrlen)
FUNC1(uint, ssh_rsakex_klen, val_rsakex)
FUNC3(val_string, ssh_rsakex_encrypt, val_rsakex, hashalg, val_string_ptrlen)
FUNC3(opt_val_mpint, ssh_rsakex_decrypt, val_rsakex, hashalg, val_string_ptrlen)
FUNC1(val_rsakex, get_rsa_ssh1_priv_agent, val_string_binarysource)
FUNC(val_rsakex, ssh_rsakex_newkey, (ARG(val_string_ptrlen, data)))
FUNC(uint, ssh_rsakex_klen, (ARG(val_rsakex, key)))
FUNC(val_string, ssh_rsakex_encrypt, (ARG(val_rsakex, key), ARG(hashalg, h), ARG(val_string_ptrlen, plaintext)))
FUNC(opt_val_mpint, ssh_rsakex_decrypt, (ARG(val_rsakex, key), ARG(hashalg, h), ARG(val_string_ptrlen, ciphertext)))
FUNC(val_rsakex, get_rsa_ssh1_priv_agent, (ARG(val_string_binarysource, src)))
/*
* Bare RSA keys as used in SSH-1. The construction API functions
* write into an existing RSAKey object, so I've invented an 'rsa_new'
* function to make one in the first place.
*/
FUNC0(val_rsa, rsa_new)
FUNC3(void, get_rsa_ssh1_pub, val_string_binarysource, val_rsa, rsaorder)
FUNC2(void, get_rsa_ssh1_priv, val_string_binarysource, val_rsa)
FUNC2(opt_val_string, rsa_ssh1_encrypt, val_string_ptrlen, val_rsa)
FUNC2(val_mpint, rsa_ssh1_decrypt, val_mpint, val_rsa)
FUNC2(val_string, rsa_ssh1_decrypt_pkcs1, val_mpint, val_rsa)
FUNC1(val_string_asciz, rsastr_fmt, val_rsa)
FUNC1(val_string_asciz, rsa_ssh1_fingerprint, val_rsa)
FUNC3(void, rsa_ssh1_public_blob, out_val_string_binarysink, val_rsa, rsaorder)
FUNC1(int, rsa_ssh1_public_blob_len, val_string_ptrlen)
FUNC2(void, rsa_ssh1_private_blob_agent, out_val_string_binarysink, val_rsa)
FUNC(val_rsa, rsa_new, (VOID))
FUNC(void, get_rsa_ssh1_pub, (ARG(val_string_binarysource, src), ARG(val_rsa, key), ARG(rsaorder, order)))
FUNC(void, get_rsa_ssh1_priv, (ARG(val_string_binarysource, src), ARG(val_rsa, key)))
FUNC(opt_val_string, rsa_ssh1_encrypt, (ARG(val_string_ptrlen, data), ARG(val_rsa, key)))
FUNC(val_mpint, rsa_ssh1_decrypt, (ARG(val_mpint, input), ARG(val_rsa, key)))
FUNC(val_string, rsa_ssh1_decrypt_pkcs1, (ARG(val_mpint, input), ARG(val_rsa, key)))
FUNC(val_string_asciz, rsastr_fmt, (ARG(val_rsa, key)))
FUNC(val_string_asciz, rsa_ssh1_fingerprint, (ARG(val_rsa, key)))
FUNC(void, rsa_ssh1_public_blob, (ARG(out_val_string_binarysink, bs), ARG(val_rsa, key), ARG(rsaorder, order)))
FUNC(int, rsa_ssh1_public_blob_len, (ARG(val_string_ptrlen, data)))
FUNC(void, rsa_ssh1_private_blob_agent, (ARG(out_val_string_binarysink, bs), ARG(val_rsa, key)))
/*
* The PRNG type. Similarly to hashes and MACs, I've invented an extra
* function prng_seed_update for putting seed data into the PRNG's
* exposed BinarySink.
*/
FUNC1(val_prng, prng_new, hashalg)
FUNC1(void, prng_seed_begin, val_prng)
FUNC2(void, prng_seed_update, val_prng, val_string_ptrlen)
FUNC1(void, prng_seed_finish, val_prng)
FUNC2(val_string, prng_read, val_prng, uint)
FUNC3(void, prng_add_entropy, val_prng, uint, val_string_ptrlen)
FUNC(val_prng, prng_new, (ARG(hashalg, hashalg)))
FUNC(void, prng_seed_begin, (ARG(val_prng, p)))
FUNC(void, prng_seed_update, (ARG(val_prng, pr), ARG(val_string_ptrlen, data)))
FUNC(void, prng_seed_finish, (ARG(val_prng, p)))
FUNC(val_string, prng_read, (ARG(val_prng, p), ARG(uint, size)))
FUNC(void, prng_add_entropy, (ARG(val_prng, p), ARG(uint, source_id), ARG(val_string_ptrlen, data)))
/*
* Key load/save functions, or rather, the BinarySource / strbuf API
* that sits just inside the file I/O versions.
*/
FUNC2(boolean, ppk_encrypted_s, val_string_binarysource, out_opt_val_string_asciz)
FUNC2(boolean, rsa1_encrypted_s, val_string_binarysource, out_opt_val_string_asciz)
FUNC5(boolean, ppk_loadpub_s, val_string_binarysource, out_opt_val_string_asciz, out_val_string_binarysink, out_opt_val_string_asciz, out_opt_val_string_asciz_const)
FUNC4(int, rsa1_loadpub_s, val_string_binarysource, out_val_string_binarysink, out_opt_val_string_asciz, out_opt_val_string_asciz_const)
FUNC4(opt_val_key, ppk_load_s, val_string_binarysource, out_opt_val_string_asciz, opt_val_string_asciz, out_opt_val_string_asciz_const)
FUNC5(int, rsa1_load_s, val_string_binarysource, val_rsa, out_opt_val_string_asciz, opt_val_string_asciz, out_opt_val_string_asciz_const)
FUNC8(val_string, ppk_save_sb, val_key, opt_val_string_asciz, opt_val_string_asciz, uint, argon2flavour, uint, uint, uint)
FUNC3(val_string, rsa1_save_sb, val_rsa, opt_val_string_asciz, opt_val_string_asciz)
FUNC(boolean, ppk_encrypted_s, (ARG(val_string_binarysource, src), ARG(out_opt_val_string_asciz, comment)))
FUNC(boolean, rsa1_encrypted_s, (ARG(val_string_binarysource, src), ARG(out_opt_val_string_asciz, comment)))
FUNC(boolean, ppk_loadpub_s, (ARG(val_string_binarysource, src), ARG(out_opt_val_string_asciz, algorithm), ARG(out_val_string_binarysink, bs), ARG(out_opt_val_string_asciz, commentptr), ARG(out_opt_val_string_asciz_const, errorstr)))
FUNC(int, rsa1_loadpub_s, (ARG(val_string_binarysource, src), ARG(out_val_string_binarysink, bs), ARG(out_opt_val_string_asciz, commentptr), ARG(out_opt_val_string_asciz_const, errorstr)))
FUNC(opt_val_key, ppk_load_s, (ARG(val_string_binarysource, src), ARG(out_opt_val_string_asciz, comment), ARG(opt_val_string_asciz, passphrase), ARG(out_opt_val_string_asciz_const, errorstr)))
FUNC(int, rsa1_load_s, (ARG(val_string_binarysource, src), ARG(val_rsa, key), ARG(out_opt_val_string_asciz, comment), ARG(opt_val_string_asciz, passphrase), ARG(out_opt_val_string_asciz_const, errorstr)))
FUNC(val_string, ppk_save_sb, (ARG(val_key, key), ARG(opt_val_string_asciz, comment), ARG(opt_val_string_asciz, passphrase), ARG(uint, fmt_version), ARG(argon2flavour, flavour), ARG(uint, mem), ARG(uint, passes), ARG(uint, parallel)))
FUNC(val_string, rsa1_save_sb, (ARG(val_rsa, key), ARG(opt_val_string_asciz, comment), ARG(opt_val_string_asciz, passphrase)))
FUNC2(val_string_asciz, ssh2_fingerprint_blob, val_string_ptrlen, fptype)
FUNC(val_string_asciz, ssh2_fingerprint_blob, (ARG(val_string_ptrlen, blob), ARG(fptype, fptype)))
/*
* Password hashing.
*/
FUNC9(val_string, argon2, argon2flavour, uint, uint, uint, uint, val_string_ptrlen, val_string_ptrlen, val_string_ptrlen, val_string_ptrlen)
FUNC2(val_string, argon2_long_hash, uint, val_string_ptrlen)
FUNC(val_string, argon2, (ARG(argon2flavour, flavour), ARG(uint, mem), ARG(uint, passes), ARG(uint, parallel), ARG(uint, taglen), ARG(val_string_ptrlen, P), ARG(val_string_ptrlen, S), ARG(val_string_ptrlen, K), ARG(val_string_ptrlen, X)))
FUNC(val_string, argon2_long_hash, (ARG(uint, length), ARG(val_string_ptrlen, data)))
/*
* Key generation functions.
*/
FUNC3(val_key, rsa_generate, uint, boolean, val_pgc)
FUNC2(val_key, dsa_generate, uint, val_pgc)
FUNC1(opt_val_key, ecdsa_generate, uint)
FUNC1(opt_val_key, eddsa_generate, uint)
FUNC3(val_rsa, rsa1_generate, uint, boolean, val_pgc)
FUNC1(val_pgc, primegen_new_context, primegenpolicy)
FUNC2(opt_val_mpint, primegen_generate, val_pgc, consumed_val_pcs)
FUNC2(val_string, primegen_mpu_certificate, val_pgc, val_mpint)
FUNC1(val_pcs, pcs_new, uint)
FUNC3(val_pcs, pcs_new_with_firstbits, uint, uint, uint)
FUNC3(void, pcs_require_residue, val_pcs, val_mpint, val_mpint)
FUNC2(void, pcs_require_residue_1, val_pcs, val_mpint)
FUNC2(void, pcs_require_residue_1_mod_prime, val_pcs, val_mpint)
FUNC3(void, pcs_avoid_residue_small, val_pcs, uint, uint)
FUNC1(void, pcs_try_sophie_germain, val_pcs)
FUNC1(void, pcs_set_oneshot, val_pcs)
FUNC1(void, pcs_ready, val_pcs)
FUNC4(void, pcs_inspect, val_pcs, out_val_mpint, out_val_mpint, out_val_mpint)
FUNC1(val_mpint, pcs_generate, val_pcs)
FUNC0(val_pockle, pockle_new)
FUNC1(uint, pockle_mark, val_pockle)
FUNC2(void, pockle_release, val_pockle, uint)
FUNC2(pocklestatus, pockle_add_small_prime, val_pockle, val_mpint)
FUNC4(pocklestatus, pockle_add_prime, val_pockle, val_mpint, mpint_list, val_mpint)
FUNC2(val_string, pockle_mpu, val_pockle, val_mpint)
FUNC1(val_millerrabin, miller_rabin_new, val_mpint)
FUNC2(mr_result, miller_rabin_test, val_millerrabin, val_mpint)
FUNC(val_key, rsa_generate, (ARG(uint, bits), ARG(boolean, strong), ARG(val_pgc, pgc)))
FUNC(val_key, dsa_generate, (ARG(uint, bits), ARG(val_pgc, pgc)))
FUNC(opt_val_key, ecdsa_generate, (ARG(uint, bits)))
FUNC(opt_val_key, eddsa_generate, (ARG(uint, bits)))
FUNC(val_rsa, rsa1_generate, (ARG(uint, bits), ARG(boolean, strong), ARG(val_pgc, pgc)))
FUNC(val_pgc, primegen_new_context, (ARG(primegenpolicy, policy)))
FUNC(opt_val_mpint, primegen_generate, (ARG(val_pgc, ctx), ARG(consumed_val_pcs, pcs)))
FUNC(val_string, primegen_mpu_certificate, (ARG(val_pgc, ctx), ARG(val_mpint, p)))
FUNC(val_pcs, pcs_new, (ARG(uint, bits)))
FUNC(val_pcs, pcs_new_with_firstbits, (ARG(uint, bits), ARG(uint, first), ARG(uint, nfirst)))
FUNC(void, pcs_require_residue, (ARG(val_pcs, s), ARG(val_mpint, mod), ARG(val_mpint, res)))
FUNC(void, pcs_require_residue_1, (ARG(val_pcs, s), ARG(val_mpint, mod)))
FUNC(void, pcs_require_residue_1_mod_prime, (ARG(val_pcs, s), ARG(val_mpint, mod)))
FUNC(void, pcs_avoid_residue_small, (ARG(val_pcs, s), ARG(uint, mod), ARG(uint, res)))
FUNC(void, pcs_try_sophie_germain, (ARG(val_pcs, s)))
FUNC(void, pcs_set_oneshot, (ARG(val_pcs, s)))
FUNC(void, pcs_ready, (ARG(val_pcs, s)))
FUNC(void, pcs_inspect, (ARG(val_pcs, pcs), ARG(out_val_mpint, limit_out), ARG(out_val_mpint, factor_out), ARG(out_val_mpint, addend_out)))
FUNC(val_mpint, pcs_generate, (ARG(val_pcs, s)))
FUNC(val_pockle, pockle_new, (VOID))
FUNC(uint, pockle_mark, (ARG(val_pockle, pockle)))
FUNC(void, pockle_release, (ARG(val_pockle, pockle), ARG(uint, mark)))
FUNC(pocklestatus, pockle_add_small_prime, (ARG(val_pockle, pockle), ARG(val_mpint, p)))
FUNC(pocklestatus, pockle_add_prime, (ARG(val_pockle, pockle), ARG(val_mpint, p), ARG(mpint_list, factors), ARG(val_mpint, witness)))
FUNC(val_string, pockle_mpu, (ARG(val_pockle, pockle), ARG(val_mpint, p)))
FUNC(val_millerrabin, miller_rabin_new, (ARG(val_mpint, p)))
FUNC(mr_result, miller_rabin_test, (ARG(val_millerrabin, mr), ARG(val_mpint, w)))
/*
* Miscellaneous.
*/
FUNC2(val_wpoint, ecdsa_public, val_mpint, keyalg)
FUNC2(val_epoint, eddsa_public, val_mpint, keyalg)
FUNC2(val_string, des_encrypt_xdmauth, val_string_ptrlen, val_string_ptrlen)
FUNC2(val_string, des_decrypt_xdmauth, val_string_ptrlen, val_string_ptrlen)
FUNC2(val_string, des3_encrypt_pubkey, val_string_ptrlen, val_string_ptrlen)
FUNC2(val_string, des3_decrypt_pubkey, val_string_ptrlen, val_string_ptrlen)
FUNC3(val_string, des3_encrypt_pubkey_ossh, val_string_ptrlen, val_string_ptrlen, val_string_ptrlen)
FUNC3(val_string, des3_decrypt_pubkey_ossh, val_string_ptrlen, val_string_ptrlen, val_string_ptrlen)
FUNC3(val_string, aes256_encrypt_pubkey, val_string_ptrlen, val_string_ptrlen, val_string_ptrlen)
FUNC3(val_string, aes256_decrypt_pubkey, val_string_ptrlen, val_string_ptrlen, val_string_ptrlen)
FUNC1(uint, crc32_rfc1662, val_string_ptrlen)
FUNC1(uint, crc32_ssh1, val_string_ptrlen)
FUNC2(uint, crc32_update, uint, val_string_ptrlen)
FUNC2(boolean, crcda_detect, val_string_ptrlen, val_string_ptrlen)
FUNC1(val_string, get_implementations_commasep, val_string_ptrlen)
FUNC12(void, http_digest_response, out_val_string_binarysink, val_string_ptrlen, val_string_ptrlen, val_string_ptrlen, val_string_ptrlen, val_string_ptrlen, val_string_ptrlen, val_string_ptrlen, val_string_ptrlen, uint, httpdigesthash, boolean)
FUNC(val_wpoint, ecdsa_public, (ARG(val_mpint, private_key), ARG(keyalg, alg)))
FUNC(val_epoint, eddsa_public, (ARG(val_mpint, private_key), ARG(keyalg, alg)))
FUNC(val_string, des_encrypt_xdmauth, (ARG(val_string_ptrlen, key), ARG(val_string_ptrlen, blk)))
FUNC(val_string, des_decrypt_xdmauth, (ARG(val_string_ptrlen, key), ARG(val_string_ptrlen, blk)))
FUNC(val_string, des3_encrypt_pubkey, (ARG(val_string_ptrlen, key), ARG(val_string_ptrlen, blk)))
FUNC(val_string, des3_decrypt_pubkey, (ARG(val_string_ptrlen, key), ARG(val_string_ptrlen, blk)))
FUNC(val_string, des3_encrypt_pubkey_ossh, (ARG(val_string_ptrlen, key), ARG(val_string_ptrlen, iv), ARG(val_string_ptrlen, blk)))
FUNC(val_string, des3_decrypt_pubkey_ossh, (ARG(val_string_ptrlen, key), ARG(val_string_ptrlen, iv), ARG(val_string_ptrlen, blk)))
FUNC(val_string, aes256_encrypt_pubkey, (ARG(val_string_ptrlen, key), ARG(val_string_ptrlen, iv), ARG(val_string_ptrlen, blk)))
FUNC(val_string, aes256_decrypt_pubkey, (ARG(val_string_ptrlen, key), ARG(val_string_ptrlen, iv), ARG(val_string_ptrlen, blk)))
FUNC(uint, crc32_rfc1662, (ARG(val_string_ptrlen, data)))
FUNC(uint, crc32_ssh1, (ARG(val_string_ptrlen, data)))
FUNC(uint, crc32_update, (ARG(uint, crc_input), ARG(val_string_ptrlen, data)))
FUNC(boolean, crcda_detect, (ARG(val_string_ptrlen, packet), ARG(val_string_ptrlen, iv)))
FUNC(val_string, get_implementations_commasep, (ARG(val_string_ptrlen, alg)))
FUNC(void, http_digest_response, (ARG(out_val_string_binarysink, bs), ARG(val_string_ptrlen, username), ARG(val_string_ptrlen, password), ARG(val_string_ptrlen, realm), ARG(val_string_ptrlen, method), ARG(val_string_ptrlen, uri), ARG(val_string_ptrlen, qop), ARG(val_string_ptrlen, nonce), ARG(val_string_ptrlen, opaque), ARG(uint, nonce_count), ARG(httpdigesthash, hash), ARG(boolean, hash_username)))
/*
* These functions aren't part of PuTTY's own API, but are additions
* by testcrypt itself for administrative purposes.
*/
FUNC1(void, random_queue, val_string_ptrlen)
FUNC0(uint, random_queue_len)
FUNC2(void, random_make_prng, hashalg, val_string_ptrlen)
FUNC0(void, random_clear)
FUNC(void, random_queue, (ARG(val_string_ptrlen, pl)))
FUNC(uint, random_queue_len, (VOID))
FUNC(void, random_make_prng, (ARG(hashalg, hashalg), ARG(val_string_ptrlen, seed)))
FUNC(void, random_clear, (VOID))