diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2011-06-06 11:49:36 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2011-06-06 11:49:36 +0000 |
commit | f610a516a0e1236e21b385c4719c97403fde4a98 (patch) | |
tree | f009d59dfc838d98a359c0fad453dee1acfc2583 /crypto/ec | |
parent | 2e51a4caa3bff0ff59f87f7423ba0551593ef48e (diff) |
Backport from HEAD:
New option to disable characteristic two fields in EC code.
Make no-ec2m work on Win32 build.
Diffstat (limited to 'crypto/ec')
-rw-r--r-- | crypto/ec/ec.h | 18 | ||||
-rw-r--r-- | crypto/ec/ec2_mult.c | 4 | ||||
-rw-r--r-- | crypto/ec/ec2_smpl.c | 4 | ||||
-rw-r--r-- | crypto/ec/ec_asn1.c | 24 | ||||
-rw-r--r-- | crypto/ec/ec_curve.c | 14 | ||||
-rw-r--r-- | crypto/ec/ec_cvt.c | 3 | ||||
-rw-r--r-- | crypto/ec/ec_err.c | 1 | ||||
-rw-r--r-- | crypto/ec/ec_key.c | 3 | ||||
-rw-r--r-- | crypto/ec/ec_lib.c | 16 | ||||
-rw-r--r-- | crypto/ec/eck_prn.c | 3 | ||||
-rw-r--r-- | crypto/ec/ectest.c | 4 |
11 files changed, 71 insertions, 23 deletions
diff --git a/crypto/ec/ec.h b/crypto/ec/ec.h index c95285e597..64d0a2948d 100644 --- a/crypto/ec/ec.h +++ b/crypto/ec/ec.h @@ -158,7 +158,7 @@ const EC_METHOD *EC_GFp_nist_method(void); const EC_METHOD *EC_GFp_nistp224_method(void); #endif - +#ifndef OPENSSL_NO_EC2M /********************************************************************/ /* EC_METHOD for curves over GF(2^m) */ /********************************************************************/ @@ -168,6 +168,8 @@ const EC_METHOD *EC_GFp_nistp224_method(void); */ const EC_METHOD *EC_GF2m_simple_method(void); +#endif + /********************************************************************/ /* EC_GROUP functions */ @@ -289,6 +291,7 @@ int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, co */ int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); +#ifndef OPENSSL_NO_EC2M /** Sets the parameter of a ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b * \param group EC_GROUP object * \param p BIGNUM with the polynomial defining the underlying field @@ -308,7 +311,7 @@ int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, c * \return 1 on success and 0 if an error occured */ int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); - +#endif /** Returns the number of bits needed to represent a field element * \param group EC_GROUP object * \return number of bits needed to represent a field element @@ -349,7 +352,7 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx); * \return newly created EC_GROUP object with the specified parameters */ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); - +#ifndef OPENSSL_NO_EC2M /** Creates a new EC_GROUP object with the specified parameters defined * over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b) * \param p BIGNUM with the polynomial defining the underlying field @@ -359,7 +362,7 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM * \return newly created EC_GROUP object with the specified parameters */ EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); - +#endif /** Creates a EC_GROUP object with a curve specified by a NID * \param nid NID of the OID of the curve name * \return newly created EC_GROUP object with specified curve or NULL @@ -488,7 +491,7 @@ int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, */ int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *p, const BIGNUM *x, int y_bit, BN_CTX *ctx); - +#ifndef OPENSSL_NO_EC2M /** Sets the affine coordinates of a EC_POINT over GF2m * \param group underlying EC_GROUP object * \param p EC_POINT object @@ -521,7 +524,7 @@ int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, */ int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p, const BIGNUM *x, int y_bit, BN_CTX *ctx); - +#endif /** Encodes a EC_POINT object to a octet string * \param group underlying EC_GROUP object * \param p EC_POINT object @@ -660,9 +663,11 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group); /* EC_GROUP_get_basis_type() returns the NID of the basis type * used to represent the field elements */ int EC_GROUP_get_basis_type(const EC_GROUP *); +#ifndef OPENSSL_NO_EC2M int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k); int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1, unsigned int *k2, unsigned int *k3); +#endif #define OPENSSL_EC_NAMED_CURVE 0x001 @@ -1082,6 +1087,7 @@ void ERR_load_EC_strings(void); #define EC_R_DISCRIMINANT_IS_ZERO 118 #define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119 #define EC_R_FIELD_TOO_LARGE 143 +#define EC_R_GF2M_NOT_SUPPORTED 147 #define EC_R_GROUP2PKPARAMETERS_FAILURE 120 #define EC_R_I2D_ECPKPARAMETERS_FAILURE 121 #define EC_R_INCOMPATIBLE_OBJECTS 101 diff --git a/crypto/ec/ec2_mult.c b/crypto/ec/ec2_mult.c index e12b9b284a..26f4a783fc 100644 --- a/crypto/ec/ec2_mult.c +++ b/crypto/ec/ec2_mult.c @@ -71,6 +71,8 @@ #include "ec_lcl.h" +#ifndef OPENSSL_NO_EC2M + /* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective * coordinates. @@ -384,3 +386,5 @@ int ec_GF2m_have_precompute_mult(const EC_GROUP *group) { return ec_wNAF_have_precompute_mult(group); } + +#endif diff --git a/crypto/ec/ec2_smpl.c b/crypto/ec/ec2_smpl.c index af94458ca7..a379c9b450 100644 --- a/crypto/ec/ec2_smpl.c +++ b/crypto/ec/ec2_smpl.c @@ -71,6 +71,8 @@ #include "ec_lcl.h" +#ifndef OPENSSL_NO_EC2M + const EC_METHOD *EC_GF2m_simple_method(void) { @@ -1040,3 +1042,5 @@ int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, { return BN_GF2m_mod_div(r, a, b, &group->field, ctx); } + +#endif diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c index ae55539859..175eec5342 100644 --- a/crypto/ec/ec_asn1.c +++ b/crypto/ec/ec_asn1.c @@ -83,7 +83,7 @@ int EC_GROUP_get_basis_type(const EC_GROUP *group) /* everything else is currently not supported */ return 0; } - +#ifndef OPENSSL_NO_EC2M int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k) { if (group == NULL) @@ -101,7 +101,6 @@ int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k) return 1; } - int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1, unsigned int *k2, unsigned int *k3) { @@ -124,7 +123,7 @@ int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1, return 1; } - +#endif /* some structures needed for the asn1 encoding */ @@ -340,6 +339,12 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) } } else /* nid == NID_X9_62_characteristic_two_field */ +#ifdef OPENSSL_NO_EC2M + { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED); + goto err; + } +#else { int field_type; X9_62_CHARACTERISTIC_TWO *char_two; @@ -419,6 +424,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) } } } +#endif ok = 1; @@ -456,6 +462,7 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) goto err; } } +#ifndef OPENSSL_NO_EC2M else /* nid == NID_X9_62_characteristic_two_field */ { if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL)) @@ -464,7 +471,7 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) goto err; } } - +#endif len_1 = (size_t)BN_num_bytes(tmp_1); len_2 = (size_t)BN_num_bytes(tmp_2); @@ -775,8 +782,13 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) /* get the field parameters */ tmp = OBJ_obj2nid(params->fieldID->fieldType); - if (tmp == NID_X9_62_characteristic_two_field) +#ifdef OPENSSL_NO_EC2M + { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_GF2M_NOT_SUPPORTED); + goto err; + } +#else { X9_62_CHARACTERISTIC_TWO *char_two; @@ -862,6 +874,7 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) /* create the EC_GROUP structure */ ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL); } +#endif else if (tmp == NID_X9_62_prime_field) { /* we have a curve over a prime field */ @@ -1065,6 +1078,7 @@ EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len) if ((group = ec_asn1_pkparameters2group(params)) == NULL) { ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE); + ECPKPARAMETERS_free(params); return NULL; } diff --git a/crypto/ec/ec_curve.c b/crypto/ec/ec_curve.c index 56a44d0e9e..85cd3b6b3d 100644 --- a/crypto/ec/ec_curve.c +++ b/crypto/ec/ec_curve.c @@ -703,6 +703,8 @@ static const struct { EC_CURVE_DATA h; unsigned char data[0+28*6]; } 0x13,0xDD,0x29,0x45,0x5C,0x5C,0x2A,0x3D } }; +#ifndef OPENSSL_NO_EC2M + /* characteristic two curves */ static const struct { EC_CURVE_DATA h; unsigned char data[20+15*6]; } _EC_SECG_CHAR2_113R1 = { @@ -1817,6 +1819,8 @@ static const struct { EC_CURVE_DATA h; unsigned char data[0+24*6]; } 0xBA,0xFC,0xA7,0x5E } }; +#endif + typedef struct _ec_list_element_st { int nid; const EC_CURVE_DATA *data; @@ -1855,6 +1859,7 @@ static const ec_list_element curve_list[] = { { NID_X9_62_prime239v2, &_EC_X9_62_PRIME_239V2.h, 0, "X9.62 curve over a 239 bit prime field" }, { NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0, "X9.62 curve over a 239 bit prime field" }, { NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, 0, "X9.62/SECG curve over a 256 bit prime field" }, +#ifndef OPENSSL_NO_EC2M /* characteristic two field curves */ /* NIST/SECG curves */ { NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0, "SECG curve over a 113 bit binary field" }, @@ -1898,18 +1903,23 @@ static const ec_list_element curve_list[] = { { NID_wap_wsg_idm_ecid_wtls3, &_EC_NIST_CHAR2_163K.h, 0, "NIST/SECG/WTLS curve over a 163 bit binary field" }, { NID_wap_wsg_idm_ecid_wtls4, &_EC_SECG_CHAR2_113R1.h, 0, "SECG curve over a 113 bit binary field" }, { NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0, "X9.62 curve over a 163 bit binary field" }, +#endif { NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0, "SECG/WTLS curve over a 112 bit prime field" }, { NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0, "SECG/WTLS curve over a 160 bit prime field" }, { NID_wap_wsg_idm_ecid_wtls8, &_EC_WTLS_8.h, 0, "WTLS curve over a 112 bit prime field" }, { NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0, "WTLS curve over a 160 bit prime field" }, +#ifndef OPENSSL_NO_EC2M { NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" }, { NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" }, +#endif { NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0, "WTLS curvs over a 224 bit prime field" }, +#ifndef OPENSSL_NO_EC2M /* IPSec curves */ { NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0, "\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n" "\tNot suitable for ECDSA.\n\tQuestionable extension field!" }, { NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0, "\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n" "\tNot suitable for ECDSA.\n\tQuestionable extension field!" }, +#endif }; #define curve_list_length (sizeof(curve_list)/sizeof(ec_list_element)) @@ -1964,6 +1974,7 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) goto err; } } +#ifndef OPENSSL_NO_EC2M else /* field_type == NID_X9_62_characteristic_two_field */ { if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL) @@ -1972,6 +1983,7 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) goto err; } } +#endif if ((P = EC_POINT_new(group)) == NULL) { @@ -1985,7 +1997,7 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); goto err; } - if (!EC_POINT_set_affine_coordinates_GF2m(group, P, x, y, ctx)) + if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) { ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); goto err; diff --git a/crypto/ec/ec_cvt.c b/crypto/ec/ec_cvt.c index d45640bab9..bbed1da455 100644 --- a/crypto/ec/ec_cvt.c +++ b/crypto/ec/ec_cvt.c @@ -122,7 +122,7 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM return ret; } - +#ifndef OPENSSL_NO_EC2M EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { const EC_METHOD *meth; @@ -142,3 +142,4 @@ EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM return ret; } +#endif diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c index a05e44c031..15d539cbf4 100644 --- a/crypto/ec/ec_err.c +++ b/crypto/ec/ec_err.c @@ -213,6 +213,7 @@ static ERR_STRING_DATA EC_str_reasons[]= {ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO) ,"discriminant is zero"}, {ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),"ec group new by name failure"}, {ERR_REASON(EC_R_FIELD_TOO_LARGE) ,"field too large"}, +{ERR_REASON(EC_R_GF2M_NOT_SUPPORTED) ,"gf2m not supported"}, {ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE),"group2pkparameters failure"}, {ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE),"i2d ecpkparameters failure"}, {ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS) ,"incompatible objects"}, diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index a9e780da44..2e91b5405d 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -400,7 +400,7 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y) tx = BN_CTX_get(ctx); ty = BN_CTX_get(ctx); - +#ifndef OPENSSL_NO_EC2M if (is_char_two) { if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point, @@ -411,6 +411,7 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y) goto err; } else +#endif { if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, ctx)) diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c index dd7da0fcf9..e0f0afcdf8 100644 --- a/crypto/ec/ec_lib.c +++ b/crypto/ec/ec_lib.c @@ -425,7 +425,7 @@ int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM * return group->meth->group_get_curve(group, p, a, b, ctx); } - +#ifndef OPENSSL_NO_EC2M int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { if (group->meth->group_set_curve == 0) @@ -446,7 +446,7 @@ int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM } return group->meth->group_get_curve(group, p, a, b, ctx); } - +#endif int EC_GROUP_get_degree(const EC_GROUP *group) { @@ -856,7 +856,7 @@ int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); } - +#ifndef OPENSSL_NO_EC2M int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) { @@ -872,7 +872,7 @@ int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point, } return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); } - +#endif int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) @@ -890,7 +890,7 @@ int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *p return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); } - +#ifndef OPENSSL_NO_EC2M int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) { @@ -906,7 +906,7 @@ int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT * } return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); } - +#endif int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, int y_bit, BN_CTX *ctx) @@ -924,7 +924,7 @@ int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *poi return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx); } - +#ifndef OPENSSL_NO_EC2M int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, int y_bit, BN_CTX *ctx) { @@ -940,7 +940,7 @@ int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *po } return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx); } - +#endif size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, unsigned char *buf, size_t len, BN_CTX *ctx) diff --git a/crypto/ec/eck_prn.c b/crypto/ec/eck_prn.c index 7d3e175ae7..06de8f3959 100644 --- a/crypto/ec/eck_prn.c +++ b/crypto/ec/eck_prn.c @@ -207,7 +207,7 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) reason = ERR_R_MALLOC_FAILURE; goto err; } - +#ifndef OPENSSL_NO_EC2M if (is_char_two) { if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx)) @@ -217,6 +217,7 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) } } else /* prime field */ +#endif { if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx)) { diff --git a/crypto/ec/ectest.c b/crypto/ec/ectest.c index 834d54ab59..9018e93449 100644 --- a/crypto/ec/ectest.c +++ b/crypto/ec/ectest.c @@ -776,6 +776,7 @@ static void prime_field_tests() if (!(_variable = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; \ if (!EC_GROUP_copy(_variable, group)) ABORT; \ +#ifndef OPENSSL_NO_EC2M static void char2_field_tests() { @@ -1210,6 +1211,7 @@ static void char2_field_tests() if (C2_B571) EC_GROUP_free(C2_B571); } +#endif static void internal_curve_test(void) { @@ -1391,7 +1393,9 @@ int main(int argc, char *argv[]) prime_field_tests(); puts(""); +#ifndef OPENSSL_NO_EC2M char2_field_tests(); +#endif #ifdef EC_NISTP224_64_GCC_128 nistp224_test(); #endif |