putty/testcrypt.h

245 строки
12 KiB
C
Исходник Обычный вид История

New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
/*
* mpint.h functions.
*/
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
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)
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
FUNC2(val_mpint, mp_min, val_mpint, val_mpint)
FUNC2(val_mpint, mp_max, val_mpint, val_mpint)
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
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_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, val_mpint, val_mpint)
FUNC2(val_mpint, mp_div, val_mpint, val_mpint)
FUNC2(val_mpint, mp_mod, val_mpint, 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)
FUNC2(val_modsqrt, modsqrt_new, val_mpint, val_mpint)
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
/* The modsqrt functions' 'success' pointer becomes a second return value */
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
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)
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)
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
/*
* ecc.h functions.
*/
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
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)
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
/* The output pointers in get_affine all become extra output values */
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
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)
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)
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
/*
* The ssh_hash abstraction. Note the 'consumed', indicating that
* ssh_hash_final puts its input ssh_hash beyond use.
*
* 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)
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
FUNC1(val_hash, ssh_hash_copy, val_hash)
FUNC1(val_string, ssh_hash_final, consumed_val_hash)
FUNC2(void, ssh_hash_update, val_hash, val_string_ptrlen)
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
/*
Merge the ssh1_cipher type into ssh2_cipher. The aim of this reorganisation is to make it easier to test all the ciphers in PuTTY in a uniform way. It was inconvenient that there were two separate vtable systems for the ciphers used in SSH-1 and SSH-2 with different functionality. Now there's only one type, called ssh_cipher. But really it's the old ssh2_cipher, just renamed: I haven't made any changes to the API on the SSH-2 side. Instead, I've removed ssh1_cipher completely, and adapted the SSH-1 BPP to use the SSH-2 style API. (The relevant differences are that ssh1_cipher encapsulated both the sending and receiving directions in one object - so now ssh1bpp has to make a separate cipher instance per direction - and that ssh1_cipher automatically initialised the IV to all zeroes, which ssh1bpp now has to do by hand.) The previous ssh1_cipher vtable for single-DES has been removed completely, because when converted into the new API it became identical to the SSH-2 single-DES vtable; so now there's just one vtable for DES-CBC which works in both protocols. The other two SSH-1 ciphers each had to stay separate, because 3DES is completely different between SSH-1 and SSH-2 (three layers of CBC structure versus one), and Blowfish varies in endianness and key length between the two. (Actually, while I'm here, I've only just noticed that the SSH-1 Blowfish cipher mis-describes itself in log messages as Blowfish-128. In fact it passes the whole of the input key buffer, which has length SSH1_SESSION_KEY_LENGTH == 32 bytes == 256 bits. So it's actually Blowfish-256, and has been all along!)
2019-01-17 21:06:08 +03:00
* The ssh2_mac abstraction. Note the optional ssh_cipher parameter
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
* to ssh2_mac_new. Also, again, I've invented an ssh2_mac_update so
* you can put data into the MAC.
*/
Merge the ssh1_cipher type into ssh2_cipher. The aim of this reorganisation is to make it easier to test all the ciphers in PuTTY in a uniform way. It was inconvenient that there were two separate vtable systems for the ciphers used in SSH-1 and SSH-2 with different functionality. Now there's only one type, called ssh_cipher. But really it's the old ssh2_cipher, just renamed: I haven't made any changes to the API on the SSH-2 side. Instead, I've removed ssh1_cipher completely, and adapted the SSH-1 BPP to use the SSH-2 style API. (The relevant differences are that ssh1_cipher encapsulated both the sending and receiving directions in one object - so now ssh1bpp has to make a separate cipher instance per direction - and that ssh1_cipher automatically initialised the IV to all zeroes, which ssh1bpp now has to do by hand.) The previous ssh1_cipher vtable for single-DES has been removed completely, because when converted into the new API it became identical to the SSH-2 single-DES vtable; so now there's just one vtable for DES-CBC which works in both protocols. The other two SSH-1 ciphers each had to stay separate, because 3DES is completely different between SSH-1 and SSH-2 (three layers of CBC structure versus one), and Blowfish varies in endianness and key length between the two. (Actually, while I'm here, I've only just noticed that the SSH-1 Blowfish cipher mis-describes itself in log messages as Blowfish-128. In fact it passes the whole of the input key buffer, which has length SSH1_SESSION_KEY_LENGTH == 32 bytes == 256 bits. So it's actually Blowfish-256, and has been all along!)
2019-01-17 21:06:08 +03:00
FUNC2(val_mac, ssh2_mac_new, macalg, opt_val_cipher)
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
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)
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
/*
* The ssh_key abstraction. All the uses of BinarySink and
* BinarySource in parameters are replaced with ordinary strings for
* the testing API: new_priv_openssh just takes a string input, and
* all the functions that output key and signature blobs do it by
* returning a string.
*/
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
FUNC2(val_key, ssh_key_new_pub, keyalg, val_string_ptrlen)
FUNC3(val_key, ssh_key_new_priv, keyalg, val_string_ptrlen, val_string_ptrlen)
FUNC2(val_key, ssh_key_new_priv_openssh, keyalg, val_string_binarysource)
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)
FUNC2(uint, ssh_key_public_bits, keyalg, val_string_ptrlen)
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
/*
Merge the ssh1_cipher type into ssh2_cipher. The aim of this reorganisation is to make it easier to test all the ciphers in PuTTY in a uniform way. It was inconvenient that there were two separate vtable systems for the ciphers used in SSH-1 and SSH-2 with different functionality. Now there's only one type, called ssh_cipher. But really it's the old ssh2_cipher, just renamed: I haven't made any changes to the API on the SSH-2 side. Instead, I've removed ssh1_cipher completely, and adapted the SSH-1 BPP to use the SSH-2 style API. (The relevant differences are that ssh1_cipher encapsulated both the sending and receiving directions in one object - so now ssh1bpp has to make a separate cipher instance per direction - and that ssh1_cipher automatically initialised the IV to all zeroes, which ssh1bpp now has to do by hand.) The previous ssh1_cipher vtable for single-DES has been removed completely, because when converted into the new API it became identical to the SSH-2 single-DES vtable; so now there's just one vtable for DES-CBC which works in both protocols. The other two SSH-1 ciphers each had to stay separate, because 3DES is completely different between SSH-1 and SSH-2 (three layers of CBC structure versus one), and Blowfish varies in endianness and key length between the two. (Actually, while I'm here, I've only just noticed that the SSH-1 Blowfish cipher mis-describes itself in log messages as Blowfish-128. In fact it passes the whole of the input key buffer, which has length SSH1_SESSION_KEY_LENGTH == 32 bytes == 256 bits. So it's actually Blowfish-256, and has been all along!)
2019-01-17 21:06:08 +03:00
* The ssh_cipher abstraction. The in-place encrypt and decrypt
* functions are wrapped to replace them with versions that take one
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
* string and return a separate string.
*/
Merge the ssh1_cipher type into ssh2_cipher. The aim of this reorganisation is to make it easier to test all the ciphers in PuTTY in a uniform way. It was inconvenient that there were two separate vtable systems for the ciphers used in SSH-1 and SSH-2 with different functionality. Now there's only one type, called ssh_cipher. But really it's the old ssh2_cipher, just renamed: I haven't made any changes to the API on the SSH-2 side. Instead, I've removed ssh1_cipher completely, and adapted the SSH-1 BPP to use the SSH-2 style API. (The relevant differences are that ssh1_cipher encapsulated both the sending and receiving directions in one object - so now ssh1bpp has to make a separate cipher instance per direction - and that ssh1_cipher automatically initialised the IV to all zeroes, which ssh1bpp now has to do by hand.) The previous ssh1_cipher vtable for single-DES has been removed completely, because when converted into the new API it became identical to the SSH-2 single-DES vtable; so now there's just one vtable for DES-CBC which works in both protocols. The other two SSH-1 ciphers each had to stay separate, because 3DES is completely different between SSH-1 and SSH-2 (three layers of CBC structure versus one), and Blowfish varies in endianness and key length between the two. (Actually, while I'm here, I've only just noticed that the SSH-1 Blowfish cipher mis-describes itself in log messages as Blowfish-128. In fact it passes the whole of the input key buffer, which has length SSH1_SESSION_KEY_LENGTH == 32 bytes == 256 bits. So it's actually Blowfish-256, and has been all along!)
2019-01-17 21:06:08 +03:00
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)
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
/*
* Integer Diffie-Hellman.
*/
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
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)
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
/*
* Elliptic-curve Diffie-Hellman.
*/
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
FUNC1(val_ecdh, ssh_ecdhkex_newkey, ecdh_alg)
FUNC2(void, ssh_ecdhkex_getpublic, val_ecdh, out_val_string_binarysink)
FUNC2(val_mpint, ssh_ecdhkex_getkey, val_ecdh, val_string_ptrlen)
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
/*
* RSA key exchange.
*/
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
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(val_mpint, ssh_rsakex_decrypt, val_rsakex, hashalg, val_string_ptrlen)
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
/*
* 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.
*/
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
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(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)
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
Replace PuTTY's PRNG with a Fortuna-like system. This tears out the entire previous random-pool system in sshrand.c. In its place is a system pretty close to Ferguson and Schneier's 'Fortuna' generator, with the main difference being that I use SHA-256 instead of AES for the generation side of the system (rationale given in comment). The PRNG implementation lives in sshprng.c, and defines a self- contained data type with no state stored outside the object, so you can instantiate however many of them you like. The old sshrand.c still exists, but in place of the previous random pool system, it's just become a client of sshprng.c, whose job is to hold a single global instance of the PRNG type, and manage its reference count, save file, noise-collection timers and similar administrative business. Advantages of this change include: - Fortuna is designed with a more varied threat model in mind than my old home-grown random pool. For example, after any request for random numbers, it automatically re-seeds itself, so that if the state of the PRNG should be leaked, it won't give enough information to find out what past outputs _were_. - The PRNG type can be instantiated with any hash function; the instance used by the main tools is based on SHA-256, an improvement on the old pool's use of SHA-1. - The new PRNG only uses the completely standard interface to the hash function API, instead of having to have privileged access to the internal SHA-1 block transform function. This will make it easier to revamp the hash code in general, and also it means that hardware-accelerated versions of SHA-256 will automatically be used for the PRNG as well as for everything else. - The new PRNG can be _tested_! Because it has an actual (if not quite explicit) specification for exactly what the output numbers _ought_ to be derived from the hashes of, I can (and have) put tests in cryptsuite that ensure the output really is being derived in the way I think it is. The old pool could have been returning any old nonsense and it would have been very hard to tell for sure.
2019-01-23 01:42:41 +03:00
/*
* 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)
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
/*
* Miscellaneous.
*/
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
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)
FUNC2(val_string, aes256_encrypt_pubkey, val_string_ptrlen, val_string_ptrlen)
FUNC2(val_string, aes256_decrypt_pubkey, val_string_ptrlen, val_string_ptrlen)
Expose CRC32 to testcrypt, and add tests for it. Finding even semi-official test vectors for this CRC implementation was hard, because it turns out not to _quite_ match any of the well known ones catalogued on the web. Its _polynomial_ is well known, but the combination of details that go alongside it (starting state, post-hashing transformation) are not quite the same as any other hash I know of. After trawling catalogue websites for a while I finally worked out that SSH-1's CRC and RFC 1662's CRC are basically the same except for different choices of starting value and final adjustment. And RFC 1662's CRC is common enough that there _are_ test vectors. So I've renamed the previous crc32_compute function to crc32_ssh1, reflecting that it seems to be its own thing unlike any other CRC; implemented the RFC 1662 CRC as well, as an alternative tiny wrapper on the inner crc32_update function; and exposed all three functions to testcrypt. That lets me run standard test vectors _and_ directed tests of the internal update routine, plus one check that crc32_ssh1 itself does what I expect. While I'm here, I've also modernised the code to use uint32_t in place of unsigned long, and ptrlen instead of separate pointer,length arguments. And I've removed the general primer on CRC theory from the header comment, in favour of the more specifically useful information about _which_ CRC this is and how it matches up to anything else out there. (I've bowed to inevitability and put the directed CRC tests in the 'crypt' class in cryptsuite.py. Of course this is a misnomer, since CRC isn't cryptography, but it falls into the same category in terms of the role it plays in SSH-1, and I didn't feel like making a new pointedly-named 'notreallycrypt' container class just for this :-)
2019-01-14 23:45:19 +03:00
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)
New test system for mp_int and cryptography. I've written a new standalone test program which incorporates all of PuTTY's crypto code, including the mp_int and low-level elliptic curve layers but also going all the way up to the implementations of the MAC, hash, cipher, public key and kex abstractions. The test program itself, 'testcrypt', speaks a simple line-oriented protocol on standard I/O in which you write the name of a function call followed by some inputs, and it gives you back a list of outputs preceded by a line telling you how many there are. Dynamically allocated objects are assigned string ids in the protocol, and there's a 'free' function that tells testcrypt when it can dispose of one. It's possible to speak that protocol by hand, but cumbersome. I've also provided a Python module that wraps it, by running testcrypt as a persistent subprocess and gatewaying all the function calls into things that look reasonably natural to call from Python. The Python module and testcrypt.c both read a carefully formatted header file testcrypt.h which contains the name and signature of every exported function, so it costs minimal effort to expose a given function through this test API. In a few cases it's necessary to write a wrapper in testcrypt.c that makes the function look more friendly, but mostly you don't even need that. (Though that is one of the motivations between a lot of API cleanups I've done recently!) I considered doing Python integration in the more obvious way, by linking parts of the PuTTY code directly into a native-code .so Python module. I decided against it because this way is more flexible: I can run the testcrypt program on its own, or compile it in a way that Python wouldn't play nicely with (I bet compiling just that .so with Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or attach a debugger to it. I can even recompile testcrypt for a different CPU architecture (32- vs 64-bit, or even running it on a different machine over ssh or under emulation) and still layer the nice API on top of that via the local Python interpreter. All I need is a bidirectional data channel.
2019-01-01 22:08:37 +03:00
/*
* These functions aren't part of PuTTY's own API, but are additions
* by testcrypt itself for administrative purposes.
*/
Build testcrypt on Windows. The bulk of this commit is the changes necessary to make testcrypt compile under Visual Studio. Unfortunately, I've had to remove my fiddly clever uses of C99 variadic macros, because Visual Studio does something unexpected when a variadic macro's expansion puts __VA_ARGS__ in the argument list of a further macro invocation: the commas don't separate further arguments. In other words, if you write #define INNER(x,y,z) some expansion involving x, y and z #define OUTER(...) INNER(__VA_ARGS__) OUTER(1,2,3) then gcc and clang will translate OUTER(1,2,3) into INNER(1,2,3) in the obvious way, and the inner macro will be expanded with x=1, y=2 and z=3. But try this in Visual Studio, and you'll get the macro parameter x expanding to the entire string 1,2,3 and the other two empty (with warnings complaining that INNER didn't get the number of arguments it expected). It's hard to cite chapter and verse of the standard to say which of those is _definitely_ right, though my reading leans towards the gcc/clang behaviour. But I do know I can't depend on it in code that has to compile under both! So I've removed the system that allowed me to declare everything in testcrypt.h as FUNC(ret,fn,arg,arg,arg), and now I have to use a different macro for each arity (FUNC0, FUNC1, FUNC2 etc). Also, the WRAPPED_NAME system is gone (because that too depended on the use of a comma to shift macro arguments along by one), and now I put a custom C wrapper around a function by simply re-#defining that function's own name (and therefore the subsequent code has to be a little more careful to _not_ pass functions' names between several macros before stringifying them). That's all a bit tedious, and commits me to a small amount of ongoing annoyance because now I'll have to add an explicit argument count every time I add something to testcrypt.h. But then again, perhaps it will make the code less incomprehensible to someone trying to understand it!
2019-01-11 09:25:28 +03:00
FUNC1(void, random_queue, val_string_ptrlen)
FUNC0(uint, random_queue_len)
FUNC0(void, random_clear)