Xcode 9 throws errors involving 'require'

Viewed 3926

When upgrading code to build under Xcode 9, I see compile errors in code using require and require_noerr:

    require(length > offsetof(struct blob, cert), outLabel);

The first error is: error: implicit declaration of function 'require' is invalid in C99

I also get a lot of error: use of undeclared identifier 'outLabel'. This is in RRTransactionVerifier.m which is Apple code for dealing with receipt validation.

How do I fix these errors?

2 Answers

In /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ MacOSX10.11.sdk/usr/include/AssertMacros.h require, require_noerr macros are modified now.

Follow this link: https://github.com/fontforge/fontforge/issues/3164 to check the changed list. For your error, problem is in this method. This is the modified method in VerificationController.m.

  BOOL checkReceiptSecurity(NSString *purchase_info_string, NSString *signature_string, CFDateRef purchaseDate)
{
BOOL valid = NO;
SecCertificateRef leaf = NULL, intermediate = NULL;
SecTrustRef trust = NULL;
SecPolicyRef policy = SecPolicyCreateBasicX509();

NSData *certificate_data;
NSArray *anchors;

/*
 Parse inputs:
 purchase_info_string and signature_string are base64 encoded JSON blobs that need to
 be decoded.
 */

__Require([purchase_info_string canBeConvertedToEncoding:NSASCIIStringEncoding] &&
        [signature_string canBeConvertedToEncoding:NSASCIIStringEncoding], outLabel);

size_t purchase_info_length;
uint8_t *purchase_info_bytes = base64_decode([purchase_info_string cStringUsingEncoding:NSASCIIStringEncoding],
                                             &purchase_info_length);

size_t signature_length;
uint8_t *signature_bytes = base64_decode([signature_string cStringUsingEncoding:NSASCIIStringEncoding],
                                         &signature_length);

__Require(purchase_info_bytes && signature_bytes, outLabel);

/*
 Binary format looks as follows:

 RECEIPTVERSION | SIGNATURE | CERTIFICATE SIZE | CERTIFICATE
 1 byte           128         4 bytes
 big endian

 Extract version, signature and certificate(s).
 Check receipt version == 2.
 Sanity check that signature is 128 bytes.
 Sanity check certificate size <= remaining payload data.
 */

 #pragma pack(push, 1)
struct signature_blob {
    uint8_t version;
    uint8_t signature[128];
    uint32_t cert_len;
    uint8_t certificate[];
} *signature_blob_ptr = (struct signature_blob *)signature_bytes;
 #pragma pack(pop)
uint32_t certificate_len;

/*
 Make sure the signature blob is long enough to safely extract the version and
 cert_len fields, then perform a sanity check on the fields.
 */
__Require(signature_length > offsetof(struct signature_blob, certificate), outLabel);
__Require(signature_blob_ptr->version == 2, outLabel);
certificate_len = ntohl(signature_blob_ptr->cert_len);

__Require(signature_length - offsetof(struct signature_blob, certificate) >= certificate_len, outLabel);

/*
 Validate certificate chains back to valid receipt signer; policy approximation for now
 set intermediate as a trust anchor; current intermediate lapses in 2016.
 */

certificate_data = [NSData dataWithBytes:signature_blob_ptr->certificate length:certificate_len];
__Require(leaf = SecCertificateCreateWithData(NULL, (__bridge CFDataRef) certificate_data), outLabel);

certificate_data = [NSData dataWithBytes:iTS_intermediate_der length:iTS_intermediate_der_len];
__Require(intermediate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef) certificate_data), outLabel);

anchors = [NSArray arrayWithObject:(__bridge id)intermediate];
__Require(anchors, outLabel);

__Require_noErr(SecTrustCreateWithCertificates(leaf, policy, &trust), outLabel);
__Require_noErr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef) anchors), outLabel);

if (purchaseDate)
{
    __Require_noErr(SecTrustSetVerifyDate(trust, purchaseDate), outLabel);
}

SecTrustResultType trust_result;
__Require_noErr(SecTrustEvaluate(trust, &trust_result), outLabel);
__Require(trust_result == kSecTrustResultUnspecified, outLabel);

__Require(2 == SecTrustGetCertificateCount(trust), outLabel);

/*
 Chain is valid, use leaf key to verify signature on receipt by
 calculating SHA1(version|purchaseInfo)
 */

CC_SHA1_CTX sha1_ctx;
uint8_t to_be_verified_data[CC_SHA1_DIGEST_LENGTH];

CC_SHA1_Init(&sha1_ctx);
CC_SHA1_Update(&sha1_ctx, &signature_blob_ptr->version, sizeof(signature_blob_ptr->version));
CC_SHA1_Update(&sha1_ctx, purchase_info_bytes, purchase_info_length);
CC_SHA1_Final(to_be_verified_data, &sha1_ctx);

SecKeyRef receipt_signing_key = SecTrustCopyPublicKey(trust);
__Require(receipt_signing_key, outLabel);
__Require_noErr(SecKeyRawVerify(receipt_signing_key, kSecPaddingPKCS1SHA1,
                              to_be_verified_data, sizeof(to_be_verified_data),
                              signature_blob_ptr->signature, sizeof(signature_blob_ptr->signature)),
              outLabel);

/*
 Optional:  Verify that the receipt certificate has the 1.2.840.113635.100.6.5.1 Null OID

 The signature is a 1024-bit RSA signature.
 */

valid = YES;

outLabel:
  if (leaf) CFRelease(leaf);
  if (intermediate) CFRelease(intermediate);
  if (trust) CFRelease(trust);
  if (policy) CFRelease(policy);

return valid;
}
Related