1 /* 2 * Copyright 2008-2026 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #ifndef OSSL_CRYPTO_CMS_LOCAL_H 11 #define OSSL_CRYPTO_CMS_LOCAL_H 12 13 #include <openssl/x509.h> 14 15 /* 16 * Cryptographic message syntax (CMS) structures: taken from RFC3852 17 */ 18 19 /* Forward references */ 20 21 typedef struct CMS_IssuerAndSerialNumber_st CMS_IssuerAndSerialNumber; 22 typedef struct CMS_EncapsulatedContentInfo_st CMS_EncapsulatedContentInfo; 23 typedef struct CMS_SignerIdentifier_st CMS_SignerIdentifier; 24 typedef struct CMS_OtherRevocationInfoFormat_st CMS_OtherRevocationInfoFormat; 25 typedef struct CMS_OriginatorInfo_st CMS_OriginatorInfo; 26 typedef struct CMS_EncryptedContentInfo_st CMS_EncryptedContentInfo; 27 typedef struct CMS_DigestedData_st CMS_DigestedData; 28 typedef struct CMS_EncryptedData_st CMS_EncryptedData; 29 typedef struct CMS_AuthenticatedData_st CMS_AuthenticatedData; 30 typedef struct CMS_AuthEnvelopedData_st CMS_AuthEnvelopedData; 31 typedef struct CMS_CompressedData_st CMS_CompressedData; 32 typedef struct CMS_OtherCertificateFormat_st CMS_OtherCertificateFormat; 33 typedef struct CMS_KeyTransRecipientInfo_st CMS_KeyTransRecipientInfo; 34 typedef struct CMS_OriginatorPublicKey_st CMS_OriginatorPublicKey; 35 typedef struct CMS_OriginatorIdentifierOrKey_st CMS_OriginatorIdentifierOrKey; 36 typedef struct CMS_KeyAgreeRecipientInfo_st CMS_KeyAgreeRecipientInfo; 37 typedef struct CMS_RecipientKeyIdentifier_st CMS_RecipientKeyIdentifier; 38 typedef struct CMS_KeyAgreeRecipientIdentifier_st CMS_KeyAgreeRecipientIdentifier; 39 typedef struct CMS_KEKIdentifier_st CMS_KEKIdentifier; 40 typedef struct CMS_KEKRecipientInfo_st CMS_KEKRecipientInfo; 41 typedef struct CMS_PasswordRecipientInfo_st CMS_PasswordRecipientInfo; 42 typedef struct CMS_OtherRecipientInfo_st CMS_OtherRecipientInfo; 43 typedef struct CMS_ReceiptsFrom_st CMS_ReceiptsFrom; 44 typedef struct CMS_CTX_st CMS_CTX; 45 46 struct CMS_CTX_st { 47 OSSL_LIB_CTX *libctx; 48 char *propq; 49 }; 50 51 struct CMS_ContentInfo_st { 52 ASN1_OBJECT *contentType; 53 union { 54 ASN1_OCTET_STRING *data; 55 CMS_SignedData *signedData; 56 CMS_EnvelopedData *envelopedData; 57 CMS_DigestedData *digestedData; 58 CMS_EncryptedData *encryptedData; 59 CMS_AuthEnvelopedData *authEnvelopedData; 60 CMS_AuthenticatedData *authenticatedData; 61 CMS_CompressedData *compressedData; 62 ASN1_TYPE *other; 63 /* Other types ... */ 64 void *otherData; 65 } d; 66 CMS_CTX ctx; 67 }; 68 69 DEFINE_STACK_OF(CMS_CertificateChoices) 70 71 struct CMS_SignedData_st { 72 int32_t version; 73 STACK_OF(X509_ALGOR) *digestAlgorithms; 74 CMS_EncapsulatedContentInfo *encapContentInfo; 75 STACK_OF(CMS_CertificateChoices) *certificates; 76 STACK_OF(CMS_RevocationInfoChoice) *crls; 77 STACK_OF(CMS_SignerInfo) *signerInfos; 78 }; 79 80 struct CMS_EncapsulatedContentInfo_st { 81 ASN1_OBJECT *eContentType; 82 ASN1_OCTET_STRING *eContent; 83 /* Set to 1 if incomplete structure only part set up */ 84 int partial; 85 }; 86 87 struct CMS_SignerInfo_st { 88 int32_t version; 89 CMS_SignerIdentifier *sid; 90 X509_ALGOR *digestAlgorithm; 91 STACK_OF(X509_ATTRIBUTE) *signedAttrs; 92 X509_ALGOR *signatureAlgorithm; 93 ASN1_OCTET_STRING *signature; 94 STACK_OF(X509_ATTRIBUTE) *unsignedAttrs; 95 /* Signing certificate and key */ 96 X509 *signer; 97 EVP_PKEY *pkey; 98 /* Digest and public key context for alternative parameters */ 99 EVP_MD_CTX *mctx; 100 EVP_PKEY_CTX *pctx; 101 const CMS_CTX *cms_ctx; 102 /* Set to 1 if signing time attribute is to be omitted */ 103 int omit_signing_time; 104 }; 105 106 struct CMS_SignerIdentifier_st { 107 int type; 108 union { 109 CMS_IssuerAndSerialNumber *issuerAndSerialNumber; 110 ASN1_OCTET_STRING *subjectKeyIdentifier; 111 } d; 112 }; 113 114 struct CMS_EnvelopedData_st { 115 int32_t version; 116 CMS_OriginatorInfo *originatorInfo; 117 STACK_OF(CMS_RecipientInfo) *recipientInfos; 118 CMS_EncryptedContentInfo *encryptedContentInfo; 119 STACK_OF(X509_ATTRIBUTE) *unprotectedAttrs; 120 }; 121 122 struct CMS_OriginatorInfo_st { 123 STACK_OF(CMS_CertificateChoices) *certificates; 124 STACK_OF(CMS_RevocationInfoChoice) *crls; 125 }; 126 127 struct CMS_EncryptedContentInfo_st { 128 ASN1_OBJECT *contentType; 129 X509_ALGOR *contentEncryptionAlgorithm; 130 ASN1_OCTET_STRING *encryptedContent; 131 /* Content encryption algorithm, key and tag */ 132 const EVP_CIPHER *cipher; 133 unsigned char *key; 134 size_t keylen; 135 unsigned char *tag; 136 size_t taglen; 137 /* Set to 1 if we are debugging decrypt and don't fake keys for MMA */ 138 int debug; 139 /* Set to 1 if we have no cert and need extra safety measures for MMA */ 140 int havenocert; 141 }; 142 143 struct CMS_RecipientInfo_st { 144 int type; 145 union { 146 CMS_KeyTransRecipientInfo *ktri; 147 CMS_KeyAgreeRecipientInfo *kari; 148 CMS_KEKRecipientInfo *kekri; 149 CMS_PasswordRecipientInfo *pwri; 150 CMS_OtherRecipientInfo *ori; 151 } d; 152 }; 153 154 typedef CMS_SignerIdentifier CMS_RecipientIdentifier; 155 156 struct CMS_KeyTransRecipientInfo_st { 157 int32_t version; 158 CMS_RecipientIdentifier *rid; 159 X509_ALGOR *keyEncryptionAlgorithm; 160 ASN1_OCTET_STRING *encryptedKey; 161 /* Recipient Key and cert */ 162 X509 *recip; 163 EVP_PKEY *pkey; 164 /* Public key context for this operation */ 165 EVP_PKEY_CTX *pctx; 166 const CMS_CTX *cms_ctx; 167 }; 168 169 struct CMS_KeyAgreeRecipientInfo_st { 170 int32_t version; 171 CMS_OriginatorIdentifierOrKey *originator; 172 ASN1_OCTET_STRING *ukm; 173 X509_ALGOR *keyEncryptionAlgorithm; 174 STACK_OF(CMS_RecipientEncryptedKey) *recipientEncryptedKeys; 175 /* Public key context associated with current operation */ 176 EVP_PKEY_CTX *pctx; 177 /* Cipher context for CEK wrapping */ 178 EVP_CIPHER_CTX *ctx; 179 const CMS_CTX *cms_ctx; 180 }; 181 182 struct CMS_OriginatorIdentifierOrKey_st { 183 int type; 184 union { 185 CMS_IssuerAndSerialNumber *issuerAndSerialNumber; 186 ASN1_OCTET_STRING *subjectKeyIdentifier; 187 CMS_OriginatorPublicKey *originatorKey; 188 } d; 189 }; 190 191 struct CMS_OriginatorPublicKey_st { 192 X509_ALGOR *algorithm; 193 ASN1_BIT_STRING *publicKey; 194 }; 195 196 struct CMS_RecipientEncryptedKey_st { 197 CMS_KeyAgreeRecipientIdentifier *rid; 198 ASN1_OCTET_STRING *encryptedKey; 199 /* Public key associated with this recipient */ 200 EVP_PKEY *pkey; 201 }; 202 203 struct CMS_KeyAgreeRecipientIdentifier_st { 204 int type; 205 union { 206 CMS_IssuerAndSerialNumber *issuerAndSerialNumber; 207 CMS_RecipientKeyIdentifier *rKeyId; 208 } d; 209 }; 210 211 struct CMS_RecipientKeyIdentifier_st { 212 ASN1_OCTET_STRING *subjectKeyIdentifier; 213 ASN1_GENERALIZEDTIME *date; 214 CMS_OtherKeyAttribute *other; 215 }; 216 217 struct CMS_KEKRecipientInfo_st { 218 int32_t version; 219 CMS_KEKIdentifier *kekid; 220 X509_ALGOR *keyEncryptionAlgorithm; 221 ASN1_OCTET_STRING *encryptedKey; 222 /* Extra info: symmetric key to use */ 223 unsigned char *key; 224 size_t keylen; 225 const CMS_CTX *cms_ctx; 226 }; 227 228 struct CMS_KEKIdentifier_st { 229 ASN1_OCTET_STRING *keyIdentifier; 230 ASN1_GENERALIZEDTIME *date; 231 CMS_OtherKeyAttribute *other; 232 }; 233 234 struct CMS_PasswordRecipientInfo_st { 235 int32_t version; 236 X509_ALGOR *keyDerivationAlgorithm; 237 X509_ALGOR *keyEncryptionAlgorithm; 238 ASN1_OCTET_STRING *encryptedKey; 239 /* Extra info: password to use */ 240 unsigned char *pass; 241 size_t passlen; 242 const CMS_CTX *cms_ctx; 243 }; 244 245 struct CMS_OtherRecipientInfo_st { 246 ASN1_OBJECT *oriType; 247 ASN1_TYPE *oriValue; 248 }; 249 250 struct CMS_DigestedData_st { 251 int32_t version; 252 X509_ALGOR *digestAlgorithm; 253 CMS_EncapsulatedContentInfo *encapContentInfo; 254 ASN1_OCTET_STRING *digest; 255 }; 256 257 struct CMS_EncryptedData_st { 258 int32_t version; 259 CMS_EncryptedContentInfo *encryptedContentInfo; 260 STACK_OF(X509_ATTRIBUTE) *unprotectedAttrs; 261 }; 262 263 struct CMS_AuthenticatedData_st { 264 int32_t version; 265 CMS_OriginatorInfo *originatorInfo; 266 STACK_OF(CMS_RecipientInfo) *recipientInfos; 267 X509_ALGOR *macAlgorithm; 268 X509_ALGOR *digestAlgorithm; 269 CMS_EncapsulatedContentInfo *encapContentInfo; 270 STACK_OF(X509_ATTRIBUTE) *authAttrs; 271 ASN1_OCTET_STRING *mac; 272 STACK_OF(X509_ATTRIBUTE) *unauthAttrs; 273 }; 274 275 struct CMS_AuthEnvelopedData_st { 276 int32_t version; 277 CMS_OriginatorInfo *originatorInfo; 278 STACK_OF(CMS_RecipientInfo) *recipientInfos; 279 CMS_EncryptedContentInfo *authEncryptedContentInfo; 280 STACK_OF(X509_ATTRIBUTE) *authAttrs; 281 ASN1_OCTET_STRING *mac; 282 STACK_OF(X509_ATTRIBUTE) *unauthAttrs; 283 }; 284 285 struct CMS_CompressedData_st { 286 int32_t version; 287 X509_ALGOR *compressionAlgorithm; 288 STACK_OF(CMS_RecipientInfo) *recipientInfos; 289 CMS_EncapsulatedContentInfo *encapContentInfo; 290 }; 291 292 struct CMS_RevocationInfoChoice_st { 293 int type; 294 union { 295 X509_CRL *crl; 296 CMS_OtherRevocationInfoFormat *other; 297 } d; 298 }; 299 300 #define CMS_REVCHOICE_CRL 0 301 #define CMS_REVCHOICE_OTHER 1 302 303 struct CMS_OtherRevocationInfoFormat_st { 304 ASN1_OBJECT *otherRevInfoFormat; 305 ASN1_TYPE *otherRevInfo; 306 }; 307 308 struct CMS_CertificateChoices { 309 int type; 310 union { 311 X509 *certificate; 312 ASN1_STRING *extendedCertificate; /* Obsolete */ 313 ASN1_STRING *v1AttrCert; /* Left encoded for now */ 314 ASN1_STRING *v2AttrCert; /* Left encoded for now */ 315 CMS_OtherCertificateFormat *other; 316 } d; 317 }; 318 319 #define CMS_CERTCHOICE_CERT 0 320 #define CMS_CERTCHOICE_EXCERT 1 321 #define CMS_CERTCHOICE_V1ACERT 2 322 #define CMS_CERTCHOICE_V2ACERT 3 323 #define CMS_CERTCHOICE_OTHER 4 324 325 struct CMS_OtherCertificateFormat_st { 326 ASN1_OBJECT *otherCertFormat; 327 ASN1_TYPE *otherCert; 328 }; 329 330 /* 331 * This is also defined in pkcs7.h but we duplicate it to allow the CMS code 332 * to be independent of PKCS#7 333 */ 334 335 struct CMS_IssuerAndSerialNumber_st { 336 X509_NAME *issuer; 337 ASN1_INTEGER *serialNumber; 338 }; 339 340 struct CMS_OtherKeyAttribute_st { 341 ASN1_OBJECT *keyAttrId; 342 ASN1_TYPE *keyAttr; 343 }; 344 345 /* ESS structures */ 346 347 struct CMS_ReceiptRequest_st { 348 ASN1_OCTET_STRING *signedContentIdentifier; 349 CMS_ReceiptsFrom *receiptsFrom; 350 STACK_OF(GENERAL_NAMES) *receiptsTo; 351 }; 352 353 struct CMS_ReceiptsFrom_st { 354 int type; 355 union { 356 int32_t allOrFirstTier; 357 STACK_OF(GENERAL_NAMES) *receiptList; 358 } d; 359 }; 360 361 struct CMS_Receipt_st { 362 int32_t version; 363 ASN1_OBJECT *contentType; 364 ASN1_OCTET_STRING *signedContentIdentifier; 365 ASN1_OCTET_STRING *originatorSignatureValue; 366 }; 367 368 DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo) 369 DECLARE_ASN1_ITEM(CMS_SignerInfo) 370 DECLARE_ASN1_ITEM(CMS_EncryptedContentInfo) 371 DECLARE_ASN1_ITEM(CMS_IssuerAndSerialNumber) 372 DECLARE_ASN1_ITEM(CMS_Attributes_Sign) 373 DECLARE_ASN1_ITEM(CMS_Attributes_Verify) 374 /* The authAttrs AAD encoding matches the signed-attributes one */ 375 #define CMS_Attributes_AadEncrypt_it CMS_Attributes_Sign_it 376 #define CMS_Attributes_AadDecrypt_it CMS_Attributes_Verify_it 377 DECLARE_ASN1_ITEM(CMS_RecipientInfo) 378 DECLARE_ASN1_ITEM(CMS_PasswordRecipientInfo) 379 DECLARE_ASN1_ALLOC_FUNCTIONS(CMS_IssuerAndSerialNumber) 380 381 #define CMS_SIGNERINFO_ISSUER_SERIAL 0 382 #define CMS_SIGNERINFO_KEYIDENTIFIER 1 383 384 #define CMS_RECIPINFO_ISSUER_SERIAL 0 385 #define CMS_RECIPINFO_KEYIDENTIFIER 1 386 387 #define CMS_REK_ISSUER_SERIAL 0 388 #define CMS_REK_KEYIDENTIFIER 1 389 390 #define CMS_OIK_ISSUER_SERIAL 0 391 #define CMS_OIK_KEYIDENTIFIER 1 392 #define CMS_OIK_PUBKEY 2 393 394 BIO *ossl_cms_content_bio(CMS_ContentInfo *cms); 395 const CMS_CTX *ossl_cms_get0_cmsctx(const CMS_ContentInfo *cms); 396 OSSL_LIB_CTX *ossl_cms_ctx_get0_libctx(const CMS_CTX *ctx); 397 const char *ossl_cms_ctx_get0_propq(const CMS_CTX *ctx); 398 void ossl_cms_resolve_libctx(CMS_ContentInfo *ci); 399 400 CMS_ContentInfo *ossl_cms_Data_create(OSSL_LIB_CTX *ctx, const char *propq); 401 int ossl_cms_DataFinal(CMS_ContentInfo *cms, BIO *cmsbio, 402 const unsigned char *precomp_md, 403 unsigned int precomp_mdlen); 404 405 CMS_ContentInfo *ossl_cms_DigestedData_create(const EVP_MD *md, 406 OSSL_LIB_CTX *libctx, 407 const char *propq); 408 BIO *ossl_cms_DigestedData_init_bio(const CMS_ContentInfo *cms); 409 int ossl_cms_DigestedData_do_final(const CMS_ContentInfo *cms, 410 BIO *chain, int verify); 411 412 BIO *ossl_cms_SignedData_init_bio(CMS_ContentInfo *cms); 413 int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain, 414 const unsigned char *precomp_md, 415 unsigned int precomp_mdlen); 416 int ossl_cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, 417 int type, const CMS_CTX *ctx); 418 int ossl_cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid, 419 ASN1_OCTET_STRING **keyid, 420 X509_NAME **issuer, 421 ASN1_INTEGER **sno); 422 int ossl_cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert); 423 424 CMS_ContentInfo *ossl_cms_CompressedData_create(int comp_nid, 425 OSSL_LIB_CTX *libctx, 426 const char *propq); 427 BIO *ossl_cms_CompressedData_init_bio(const CMS_ContentInfo *cms); 428 429 BIO *ossl_cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm, 430 const CMS_CTX *ctx); 431 int ossl_cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, 432 X509_ALGOR *mdalg); 433 434 int ossl_cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert); 435 int ossl_cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert); 436 int ossl_cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert); 437 int ossl_cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert); 438 439 BIO *ossl_cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec, 440 const CMS_CTX *ctx, int auth); 441 BIO *ossl_cms_EncryptedData_init_bio(const CMS_ContentInfo *cms); 442 int ossl_cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, 443 const EVP_CIPHER *cipher, 444 const unsigned char *key, size_t keylen, 445 const CMS_CTX *ctx); 446 447 int ossl_cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms); 448 int ossl_cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src); 449 ASN1_OCTET_STRING *ossl_cms_encode_Receipt(CMS_SignerInfo *si); 450 451 BIO *ossl_cms_EnvelopedData_init_bio(CMS_ContentInfo *cms); 452 int ossl_cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain); 453 BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms); 454 int ossl_cms_AuthEnvelopedData_final(CMS_ContentInfo *cms, BIO *cmsbio); 455 CMS_EnvelopedData *ossl_cms_get0_enveloped(CMS_ContentInfo *cms); 456 CMS_AuthEnvelopedData *ossl_cms_get0_auth_enveloped(CMS_ContentInfo *cms); 457 CMS_EncryptedContentInfo *ossl_cms_get0_env_enc_content(const CMS_ContentInfo *cms); 458 459 /* RecipientInfo routines */ 460 int ossl_cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd); 461 int ossl_cms_pkey_get_ri_type(EVP_PKEY *pk); 462 int ossl_cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type); 463 464 void ossl_cms_RecipientInfos_set_cmsctx(CMS_ContentInfo *cms); 465 466 /* KARI routines */ 467 int ossl_cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, 468 EVP_PKEY *recipPubKey, X509 *originator, 469 EVP_PKEY *originatorPrivKey, 470 unsigned int flags, 471 const CMS_CTX *ctx); 472 int ossl_cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms, 473 CMS_RecipientInfo *ri); 474 475 /* PWRI routines */ 476 int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, 477 CMS_RecipientInfo *ri, int en_de); 478 /* SignerInfo routines */ 479 int ossl_cms_si_check_attributes(const CMS_SignerInfo *si); 480 void ossl_cms_SignerInfos_set_cmsctx(CMS_ContentInfo *cms); 481 482 /* ESS routines */ 483 int ossl_cms_check_signing_certs(const CMS_SignerInfo *si, 484 const STACK_OF(X509) *chain); 485 486 int ossl_cms_dh_envelope(CMS_RecipientInfo *ri, int decrypt); 487 int ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt); 488 int ossl_cms_rsa_envelope(CMS_RecipientInfo *ri, int decrypt); 489 int ossl_cms_rsa_sign(CMS_SignerInfo *si, int verify); 490 491 int ossl_cms_get1_certs_ex(CMS_ContentInfo *cms, STACK_OF(X509) **certs); 492 int ossl_cms_get1_crls_ex(CMS_ContentInfo *cms, STACK_OF(X509_CRL) **crls); 493 494 DECLARE_ASN1_ITEM(CMS_CertificateChoices) 495 DECLARE_ASN1_ITEM(CMS_DigestedData) 496 DECLARE_ASN1_ITEM(CMS_EncryptedData) 497 DECLARE_ASN1_ITEM(CMS_EnvelopedData) 498 DECLARE_ASN1_ITEM(CMS_AuthEnvelopedData) 499 DECLARE_ASN1_ITEM(CMS_KEKRecipientInfo) 500 DECLARE_ASN1_ITEM(CMS_KeyAgreeRecipientInfo) 501 DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo) 502 DECLARE_ASN1_ITEM(CMS_OriginatorPublicKey) 503 DECLARE_ASN1_ITEM(CMS_OtherKeyAttribute) 504 DECLARE_ASN1_ITEM(CMS_Receipt) 505 DECLARE_ASN1_ITEM(CMS_ReceiptRequest) 506 DECLARE_ASN1_ITEM(CMS_RecipientEncryptedKey) 507 DECLARE_ASN1_ITEM(CMS_RecipientKeyIdentifier) 508 DECLARE_ASN1_ITEM(CMS_RevocationInfoChoice) 509 DECLARE_ASN1_ITEM(CMS_SignedData) 510 DECLARE_ASN1_ITEM(CMS_CompressedData) 511 512 #endif 513