1 /* 2 * loader.h - load platform dependent DSO containing freebl implementation. 3 * 4 * ***** BEGIN LICENSE BLOCK ***** 5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 6 * 7 * The contents of this file are subject to the Mozilla Public License Version 8 * 1.1 (the "License"); you may not use this file except in compliance with 9 * the License. You may obtain a copy of the License at 10 * http://www.mozilla.org/MPL/ 11 * 12 * Software distributed under the License is distributed on an "AS IS" basis, 13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 14 * for the specific language governing rights and limitations under the 15 * License. 16 * 17 * The Original Code is the Netscape security libraries. 18 * 19 * The Initial Developer of the Original Code is 20 * Netscape Communications Corporation. 21 * Portions created by the Initial Developer are Copyright (C) 2000 22 * the Initial Developer. All Rights Reserved. 23 * 24 * Contributor(s): 25 * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories 26 * 27 * Alternatively, the contents of this file may be used under the terms of 28 * either the GNU General Public License Version 2 or later (the "GPL"), or 29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 30 * in which case the provisions of the GPL or the LGPL are applicable instead 31 * of those above. If you wish to allow use of your version of this file only 32 * under the terms of either the GPL or the LGPL, and not to allow others to 33 * use your version of this file under the terms of the MPL, indicate your 34 * decision by deleting the provisions above and replace them with the notice 35 * and other provisions required by the GPL or the LGPL. If you do not delete 36 * the provisions above, a recipient may use your version of this file under 37 * the terms of any one of the MPL, the GPL or the LGPL. 38 * 39 * ***** END LICENSE BLOCK ***** */ 40 /* $Id: loader.h,v 1.26 2009/03/29 03:45:32 wtc%google.com Exp $ */ 41 42 #ifndef _LOADER_H_ 43 #define _LOADER_H_ 1 44 45 #include "blapi.h" 46 47 #define FREEBL_VERSION 0x030B 48 49 struct FREEBLVectorStr { 50 51 unsigned short length; /* of this struct in bytes */ 52 unsigned short version; /* of this struct. */ 53 54 RSAPrivateKey * (* p_RSA_NewKey)(int keySizeInBits, 55 SECItem * publicExponent); 56 57 SECStatus (* p_RSA_PublicKeyOp) (RSAPublicKey * key, 58 unsigned char * output, 59 const unsigned char * input); 60 61 SECStatus (* p_RSA_PrivateKeyOp)(RSAPrivateKey * key, 62 unsigned char * output, 63 const unsigned char * input); 64 65 SECStatus (* p_DSA_NewKey)(const PQGParams * params, 66 DSAPrivateKey ** privKey); 67 68 SECStatus (* p_DSA_SignDigest)(DSAPrivateKey * key, 69 SECItem * signature, 70 const SECItem * digest); 71 72 SECStatus (* p_DSA_VerifyDigest)(DSAPublicKey * key, 73 const SECItem * signature, 74 const SECItem * digest); 75 76 SECStatus (* p_DSA_NewKeyFromSeed)(const PQGParams *params, 77 const unsigned char * seed, 78 DSAPrivateKey **privKey); 79 80 SECStatus (* p_DSA_SignDigestWithSeed)(DSAPrivateKey * key, 81 SECItem * signature, 82 const SECItem * digest, 83 const unsigned char * seed); 84 85 SECStatus (* p_DH_GenParam)(int primeLen, DHParams ** params); 86 87 SECStatus (* p_DH_NewKey)(DHParams * params, 88 DHPrivateKey ** privKey); 89 90 SECStatus (* p_DH_Derive)(SECItem * publicValue, 91 SECItem * prime, 92 SECItem * privateValue, 93 SECItem * derivedSecret, 94 unsigned int maxOutBytes); 95 96 SECStatus (* p_KEA_Derive)(SECItem *prime, 97 SECItem *public1, 98 SECItem *public2, 99 SECItem *private1, 100 SECItem *private2, 101 SECItem *derivedSecret); 102 103 PRBool (* p_KEA_Verify)(SECItem *Y, SECItem *prime, SECItem *subPrime); 104 105 RC4Context * (* p_RC4_CreateContext)(const unsigned char *key, int len); 106 107 void (* p_RC4_DestroyContext)(RC4Context *cx, PRBool freeit); 108 109 SECStatus (* p_RC4_Encrypt)(RC4Context *cx, unsigned char *output, 110 unsigned int *outputLen, unsigned int maxOutputLen, 111 const unsigned char *input, unsigned int inputLen); 112 113 SECStatus (* p_RC4_Decrypt)(RC4Context *cx, unsigned char *output, 114 unsigned int *outputLen, unsigned int maxOutputLen, 115 const unsigned char *input, unsigned int inputLen); 116 117 RC2Context * (* p_RC2_CreateContext)(const unsigned char *key, 118 unsigned int len, const unsigned char *iv, 119 int mode, unsigned effectiveKeyLen); 120 121 void (* p_RC2_DestroyContext)(RC2Context *cx, PRBool freeit); 122 123 SECStatus (* p_RC2_Encrypt)(RC2Context *cx, unsigned char *output, 124 unsigned int *outputLen, unsigned int maxOutputLen, 125 const unsigned char *input, unsigned int inputLen); 126 127 SECStatus (* p_RC2_Decrypt)(RC2Context *cx, unsigned char *output, 128 unsigned int *outputLen, unsigned int maxOutputLen, 129 const unsigned char *input, unsigned int inputLen); 130 131 RC5Context *(* p_RC5_CreateContext)(const SECItem *key, unsigned int rounds, 132 unsigned int wordSize, const unsigned char *iv, int mode); 133 134 void (* p_RC5_DestroyContext)(RC5Context *cx, PRBool freeit); 135 136 SECStatus (* p_RC5_Encrypt)(RC5Context *cx, unsigned char *output, 137 unsigned int *outputLen, unsigned int maxOutputLen, 138 const unsigned char *input, unsigned int inputLen); 139 140 SECStatus (* p_RC5_Decrypt)(RC5Context *cx, unsigned char *output, 141 unsigned int *outputLen, unsigned int maxOutputLen, 142 const unsigned char *input, unsigned int inputLen); 143 144 DESContext *(* p_DES_CreateContext)(const unsigned char *key, 145 const unsigned char *iv, 146 int mode, PRBool encrypt); 147 148 void (* p_DES_DestroyContext)(DESContext *cx, PRBool freeit); 149 150 SECStatus (* p_DES_Encrypt)(DESContext *cx, unsigned char *output, 151 unsigned int *outputLen, unsigned int maxOutputLen, 152 const unsigned char *input, unsigned int inputLen); 153 154 SECStatus (* p_DES_Decrypt)(DESContext *cx, unsigned char *output, 155 unsigned int *outputLen, unsigned int maxOutputLen, 156 const unsigned char *input, unsigned int inputLen); 157 158 AESContext * (* p_AES_CreateContext)(const unsigned char *key, 159 const unsigned char *iv, 160 int mode, int encrypt, unsigned int keylen, 161 unsigned int blocklen); 162 163 void (* p_AES_DestroyContext)(AESContext *cx, PRBool freeit); 164 165 SECStatus (* p_AES_Encrypt)(AESContext *cx, unsigned char *output, 166 unsigned int *outputLen, unsigned int maxOutputLen, 167 const unsigned char *input, unsigned int inputLen); 168 169 SECStatus (* p_AES_Decrypt)(AESContext *cx, unsigned char *output, 170 unsigned int *outputLen, unsigned int maxOutputLen, 171 const unsigned char *input, unsigned int inputLen); 172 173 SECStatus (* p_MD5_Hash)(unsigned char *dest, const char *src); 174 175 SECStatus (* p_MD5_HashBuf)(unsigned char *dest, const unsigned char *src, 176 uint32 src_length); 177 178 MD5Context *(* p_MD5_NewContext)(void); 179 180 void (* p_MD5_DestroyContext)(MD5Context *cx, PRBool freeit); 181 182 void (* p_MD5_Begin)(MD5Context *cx); 183 184 void (* p_MD5_Update)(MD5Context *cx, 185 const unsigned char *input, unsigned int inputLen); 186 187 void (* p_MD5_End)(MD5Context *cx, unsigned char *digest, 188 unsigned int *digestLen, unsigned int maxDigestLen); 189 190 unsigned int (* p_MD5_FlattenSize)(MD5Context *cx); 191 192 SECStatus (* p_MD5_Flatten)(MD5Context *cx,unsigned char *space); 193 194 MD5Context * (* p_MD5_Resurrect)(unsigned char *space, void *arg); 195 196 void (* p_MD5_TraceState)(MD5Context *cx); 197 198 SECStatus (* p_MD2_Hash)(unsigned char *dest, const char *src); 199 200 MD2Context *(* p_MD2_NewContext)(void); 201 202 void (* p_MD2_DestroyContext)(MD2Context *cx, PRBool freeit); 203 204 void (* p_MD2_Begin)(MD2Context *cx); 205 206 void (* p_MD2_Update)(MD2Context *cx, 207 const unsigned char *input, unsigned int inputLen); 208 209 void (* p_MD2_End)(MD2Context *cx, unsigned char *digest, 210 unsigned int *digestLen, unsigned int maxDigestLen); 211 212 unsigned int (* p_MD2_FlattenSize)(MD2Context *cx); 213 214 SECStatus (* p_MD2_Flatten)(MD2Context *cx,unsigned char *space); 215 216 MD2Context * (* p_MD2_Resurrect)(unsigned char *space, void *arg); 217 218 SECStatus (* p_SHA1_Hash)(unsigned char *dest, const char *src); 219 220 SECStatus (* p_SHA1_HashBuf)(unsigned char *dest, const unsigned char *src, 221 uint32 src_length); 222 223 SHA1Context *(* p_SHA1_NewContext)(void); 224 225 void (* p_SHA1_DestroyContext)(SHA1Context *cx, PRBool freeit); 226 227 void (* p_SHA1_Begin)(SHA1Context *cx); 228 229 void (* p_SHA1_Update)(SHA1Context *cx, const unsigned char *input, 230 unsigned int inputLen); 231 232 void (* p_SHA1_End)(SHA1Context *cx, unsigned char *digest, 233 unsigned int *digestLen, unsigned int maxDigestLen); 234 235 void (* p_SHA1_TraceState)(SHA1Context *cx); 236 237 unsigned int (* p_SHA1_FlattenSize)(SHA1Context *cx); 238 239 SECStatus (* p_SHA1_Flatten)(SHA1Context *cx,unsigned char *space); 240 241 SHA1Context * (* p_SHA1_Resurrect)(unsigned char *space, void *arg); 242 243 SECStatus (* p_RNG_RNGInit)(void); 244 245 SECStatus (* p_RNG_RandomUpdate)(const void *data, size_t bytes); 246 247 SECStatus (* p_RNG_GenerateGlobalRandomBytes)(void *dest, size_t len); 248 249 void (* p_RNG_RNGShutdown)(void); 250 251 SECStatus (* p_PQG_ParamGen)(unsigned int j, PQGParams **pParams, 252 PQGVerify **pVfy); 253 254 SECStatus (* p_PQG_ParamGenSeedLen)( unsigned int j, unsigned int seedBytes, 255 PQGParams **pParams, PQGVerify **pVfy); 256 257 SECStatus (* p_PQG_VerifyParams)(const PQGParams *params, 258 const PQGVerify *vfy, SECStatus *result); 259 260 /* Version 3.001 came to here */ 261 262 SECStatus (* p_RSA_PrivateKeyOpDoubleChecked)(RSAPrivateKey *key, 263 unsigned char *output, 264 const unsigned char *input); 265 266 SECStatus (* p_RSA_PrivateKeyCheck)(RSAPrivateKey *key); 267 268 void (* p_BL_Cleanup)(void); 269 270 /* Version 3.002 came to here */ 271 272 SHA256Context *(* p_SHA256_NewContext)(void); 273 void (* p_SHA256_DestroyContext)(SHA256Context *cx, PRBool freeit); 274 void (* p_SHA256_Begin)(SHA256Context *cx); 275 void (* p_SHA256_Update)(SHA256Context *cx, const unsigned char *input, 276 unsigned int inputLen); 277 void (* p_SHA256_End)(SHA256Context *cx, unsigned char *digest, 278 unsigned int *digestLen, unsigned int maxDigestLen); 279 SECStatus (* p_SHA256_HashBuf)(unsigned char *dest, const unsigned char *src, 280 uint32 src_length); 281 SECStatus (* p_SHA256_Hash)(unsigned char *dest, const char *src); 282 void (* p_SHA256_TraceState)(SHA256Context *cx); 283 unsigned int (* p_SHA256_FlattenSize)(SHA256Context *cx); 284 SECStatus (* p_SHA256_Flatten)(SHA256Context *cx,unsigned char *space); 285 SHA256Context * (* p_SHA256_Resurrect)(unsigned char *space, void *arg); 286 287 SHA512Context *(* p_SHA512_NewContext)(void); 288 void (* p_SHA512_DestroyContext)(SHA512Context *cx, PRBool freeit); 289 void (* p_SHA512_Begin)(SHA512Context *cx); 290 void (* p_SHA512_Update)(SHA512Context *cx, const unsigned char *input, 291 unsigned int inputLen); 292 void (* p_SHA512_End)(SHA512Context *cx, unsigned char *digest, 293 unsigned int *digestLen, unsigned int maxDigestLen); 294 SECStatus (* p_SHA512_HashBuf)(unsigned char *dest, const unsigned char *src, 295 uint32 src_length); 296 SECStatus (* p_SHA512_Hash)(unsigned char *dest, const char *src); 297 void (* p_SHA512_TraceState)(SHA512Context *cx); 298 unsigned int (* p_SHA512_FlattenSize)(SHA512Context *cx); 299 SECStatus (* p_SHA512_Flatten)(SHA512Context *cx,unsigned char *space); 300 SHA512Context * (* p_SHA512_Resurrect)(unsigned char *space, void *arg); 301 302 SHA384Context *(* p_SHA384_NewContext)(void); 303 void (* p_SHA384_DestroyContext)(SHA384Context *cx, PRBool freeit); 304 void (* p_SHA384_Begin)(SHA384Context *cx); 305 void (* p_SHA384_Update)(SHA384Context *cx, const unsigned char *input, 306 unsigned int inputLen); 307 void (* p_SHA384_End)(SHA384Context *cx, unsigned char *digest, 308 unsigned int *digestLen, unsigned int maxDigestLen); 309 SECStatus (* p_SHA384_HashBuf)(unsigned char *dest, const unsigned char *src, 310 uint32 src_length); 311 SECStatus (* p_SHA384_Hash)(unsigned char *dest, const char *src); 312 void (* p_SHA384_TraceState)(SHA384Context *cx); 313 unsigned int (* p_SHA384_FlattenSize)(SHA384Context *cx); 314 SECStatus (* p_SHA384_Flatten)(SHA384Context *cx,unsigned char *space); 315 SHA384Context * (* p_SHA384_Resurrect)(unsigned char *space, void *arg); 316 317 /* Version 3.003 came to here */ 318 319 AESKeyWrapContext * (* p_AESKeyWrap_CreateContext)(const unsigned char *key, 320 const unsigned char *iv, int encrypt, unsigned int keylen); 321 322 void (* p_AESKeyWrap_DestroyContext)(AESKeyWrapContext *cx, PRBool freeit); 323 324 SECStatus (* p_AESKeyWrap_Encrypt)(AESKeyWrapContext *cx, 325 unsigned char *output, 326 unsigned int *outputLen, unsigned int maxOutputLen, 327 const unsigned char *input, unsigned int inputLen); 328 329 SECStatus (* p_AESKeyWrap_Decrypt)(AESKeyWrapContext *cx, 330 unsigned char *output, 331 unsigned int *outputLen, unsigned int maxOutputLen, 332 const unsigned char *input, unsigned int inputLen); 333 334 /* Version 3.004 came to here */ 335 336 PRBool (*p_BLAPI_SHVerify)(const char *name, PRFuncPtr addr); 337 PRBool (*p_BLAPI_VerifySelf)(const char *name); 338 339 /* Version 3.005 came to here */ 340 341 SECStatus (* p_EC_NewKey)(ECParams * params, 342 ECPrivateKey ** privKey); 343 344 SECStatus (* p_EC_NewKeyFromSeed)(ECParams * params, 345 ECPrivateKey ** privKey, 346 const unsigned char * seed, 347 int seedlen); 348 349 SECStatus (* p_EC_ValidatePublicKey)(ECParams * params, 350 SECItem * publicValue); 351 352 SECStatus (* p_ECDH_Derive)(SECItem * publicValue, 353 ECParams * params, 354 SECItem * privateValue, 355 PRBool withCofactor, 356 SECItem * derivedSecret); 357 358 SECStatus (* p_ECDSA_SignDigest)(ECPrivateKey * key, 359 SECItem * signature, 360 const SECItem * digest); 361 362 SECStatus (* p_ECDSA_VerifyDigest)(ECPublicKey * key, 363 const SECItem * signature, 364 const SECItem * digest); 365 366 SECStatus (* p_ECDSA_SignDigestWithSeed)(ECPrivateKey * key, 367 SECItem * signature, 368 const SECItem * digest, 369 const unsigned char * seed, 370 const int seedlen); 371 372 /* Version 3.006 came to here */ 373 374 /* no modification to FREEBLVectorStr itself 375 * but ECParamStr was modified 376 */ 377 378 /* Version 3.007 came to here */ 379 380 SECStatus (* p_AES_InitContext)(AESContext *cx, 381 const unsigned char *key, 382 unsigned int keylen, 383 const unsigned char *iv, 384 int mode, 385 unsigned int encrypt, 386 unsigned int blocklen); 387 SECStatus (* p_AESKeyWrap_InitContext)(AESKeyWrapContext *cx, 388 const unsigned char *key, 389 unsigned int keylen, 390 const unsigned char *iv, 391 int mode, 392 unsigned int encrypt, 393 unsigned int blocklen); 394 SECStatus (* p_DES_InitContext)(DESContext *cx, 395 const unsigned char *key, 396 unsigned int keylen, 397 const unsigned char *iv, 398 int mode, 399 unsigned int encrypt, 400 unsigned int ); 401 SECStatus (* p_RC2_InitContext)(RC2Context *cx, 402 const unsigned char *key, 403 unsigned int keylen, 404 const unsigned char *iv, 405 int mode, 406 unsigned int effectiveKeyLen, 407 unsigned int ); 408 SECStatus (* p_RC4_InitContext)(RC4Context *cx, 409 const unsigned char *key, 410 unsigned int keylen, 411 const unsigned char *, 412 int, 413 unsigned int , 414 unsigned int ); 415 416 AESContext *(*p_AES_AllocateContext)(void); 417 AESKeyWrapContext *(*p_AESKeyWrap_AllocateContext)(void); 418 DESContext *(*p_DES_AllocateContext)(void); 419 RC2Context *(*p_RC2_AllocateContext)(void); 420 RC4Context *(*p_RC4_AllocateContext)(void); 421 422 void (* p_MD2_Clone)(MD2Context *dest, MD2Context *src); 423 void (* p_MD5_Clone)(MD5Context *dest, MD5Context *src); 424 void (* p_SHA1_Clone)(SHA1Context *dest, SHA1Context *src); 425 void (* p_SHA256_Clone)(SHA256Context *dest, SHA256Context *src); 426 void (* p_SHA384_Clone)(SHA384Context *dest, SHA384Context *src); 427 void (* p_SHA512_Clone)(SHA512Context *dest, SHA512Context *src); 428 429 SECStatus (* p_TLS_PRF)(const SECItem *secret, const char *label, 430 SECItem *seed, SECItem *result, PRBool isFIPS); 431 432 const SECHashObject *(* p_HASH_GetRawHashObject)(HASH_HashType hashType); 433 434 HMACContext * (* p_HMAC_Create)(const SECHashObject *hashObj, 435 const unsigned char *secret, 436 unsigned int secret_len, PRBool isFIPS); 437 SECStatus (* p_HMAC_Init)(HMACContext *cx, const SECHashObject *hash_obj, 438 const unsigned char *secret, 439 unsigned int secret_len, PRBool isFIPS); 440 void (* p_HMAC_Begin)(HMACContext *cx); 441 void (* p_HMAC_Update)(HMACContext *cx, const unsigned char *data, 442 unsigned int data_len); 443 HMACContext * (* p_HMAC_Clone)(HMACContext *cx); 444 SECStatus (* p_HMAC_Finish)(HMACContext *cx, unsigned char *result, 445 unsigned int *result_len, 446 unsigned int max_result_len); 447 void (* p_HMAC_Destroy)(HMACContext *cx, PRBool freeit); 448 449 void (* p_RNG_SystemInfoForRNG)(void); 450 451 /* Version 3.008 came to here */ 452 453 SECStatus (* p_FIPS186Change_GenerateX)(unsigned char *XKEY, 454 const unsigned char *XSEEDj, 455 unsigned char *x_j); 456 SECStatus (* p_FIPS186Change_ReduceModQForDSA)(const unsigned char *w, 457 const unsigned char *q, 458 unsigned char *xj); 459 460 /* Version 3.009 came to here */ 461 462 SECStatus (* p_Camellia_InitContext)(CamelliaContext *cx, 463 const unsigned char *key, 464 unsigned int keylen, 465 const unsigned char *iv, 466 int mode, 467 unsigned int encrypt, 468 unsigned int unused); 469 470 CamelliaContext *(*p_Camellia_AllocateContext)(void); 471 CamelliaContext * (* p_Camellia_CreateContext)(const unsigned char *key, 472 const unsigned char *iv, 473 int mode, int encrypt, 474 unsigned int keylen); 475 void (* p_Camellia_DestroyContext)(CamelliaContext *cx, PRBool freeit); 476 477 SECStatus (* p_Camellia_Encrypt)(CamelliaContext *cx, unsigned char *output, 478 unsigned int *outputLen, 479 unsigned int maxOutputLen, 480 const unsigned char *input, 481 unsigned int inputLen); 482 483 SECStatus (* p_Camellia_Decrypt)(CamelliaContext *cx, unsigned char *output, 484 unsigned int *outputLen, 485 unsigned int maxOutputLen, 486 const unsigned char *input, 487 unsigned int inputLen); 488 489 void (* p_PQG_DestroyParams)(PQGParams *params); 490 491 void (* p_PQG_DestroyVerify)(PQGVerify *vfy); 492 493 /* Version 3.010 came to here */ 494 495 SECStatus (* p_SEED_InitContext)(SEEDContext *cx, 496 const unsigned char *key, 497 unsigned int keylen, 498 const unsigned char *iv, 499 int mode, 500 unsigned int encrypt, 501 unsigned int ); 502 503 SEEDContext *(*p_SEED_AllocateContext)(void); 504 505 SEEDContext *(* p_SEED_CreateContext)(const unsigned char *key, 506 const unsigned char *iv, 507 int mode, PRBool encrypt); 508 509 void (* p_SEED_DestroyContext)(SEEDContext *cx, PRBool freeit); 510 511 SECStatus (* p_SEED_Encrypt)(SEEDContext *cx, unsigned char *output, 512 unsigned int *outputLen, unsigned int maxOutputLen, 513 const unsigned char *input, unsigned int inputLen); 514 515 SECStatus (* p_SEED_Decrypt)(SEEDContext *cx, unsigned char *output, 516 unsigned int *outputLen, unsigned int maxOutputLen, 517 const unsigned char *input, unsigned int inputLen); 518 519 520 521 SECStatus (* p_BL_Init)(void); 522 void ( * p_BL_SetForkState)(PRBool); 523 524 SECStatus (* p_PRNGTEST_Instantiate)(const PRUint8 *entropy, 525 unsigned int entropy_len, 526 const PRUint8 *nonce, 527 unsigned int nonce_len, 528 const PRUint8 *personal_string, 529 unsigned int ps_len); 530 531 SECStatus (* p_PRNGTEST_Reseed)(const PRUint8 *entropy, 532 unsigned int entropy_len, 533 const PRUint8 *additional, 534 unsigned int additional_len); 535 536 SECStatus (* p_PRNGTEST_Generate)(PRUint8 *bytes, 537 unsigned int bytes_len, 538 const PRUint8 *additional, 539 unsigned int additional_len); 540 541 SECStatus (* p_PRNGTEST_Uninstantiate)(void); 542 /* Version 3.011 came to here */ 543 }; 544 545 typedef struct FREEBLVectorStr FREEBLVector; 546 547 SEC_BEGIN_PROTOS 548 549 typedef const FREEBLVector * FREEBLGetVectorFn(void); 550 551 extern FREEBLGetVectorFn FREEBL_GetVector; 552 553 SEC_END_PROTOS 554 555 #endif 556