---
title: Creating and using bypass codes
framework: devicemanagement
role: article
role_heading: Article
path: devicemanagement/creating-and-using-bypass-codes
---

# Creating and using bypass codes

Maintain the bypass code parameters for disabling Activation Lock.

## Overview

Overview To manage Activation Lock, your device management service needs to store two bypass codes: Device-generated bypass code: The server retains this code until it receives a different, nonempty code from the device. For more information, see the Activation Lock Bypass Code query. Server-generated bypass code: The bypass code the server creates when initiating Activation Lock through your device management service. You can attempt to unlock the device by passing in an escrow key with one of the bypass codes as its value. Try the other code if the first one fails. It’s impossible for a device management service to determine which code is active at a given time, or even to determine if the device is in a locked state, because the user can erase the device and remove Activation Lock manually by entering the correct Apple Account or password. The deviceʼs IsActivationLockEnabled value isn’t a reflection of its Activation Lock state because the device can report either a false-positive or a false-negative. note: You must request the activation lock bypass code before the device enables Activation Lock. If this sequence isn’t followed, the user may lock the device before you can install the bypass, in which case the bypass code won’t work. Create a bypass code When initiating Activation Lock for a device, you need to generate the bypass code necessary to disable Activation Lock at a later time. The following code sample shows how to generate a bypass code: #define MCBYPASS_CODE_LENGTH 31 // Excluding terminating null. #define MCBYPASS_CODE_BUFFER_LENGTH 32 // Including terminating null. #define MCBYPASS_RAW_BYTES_LENGTH 16 #define MCBYPASS_HASH_LENGTH CC_SHA256_DIGEST_LENGTH

- (NSString*) _createNewActivationLockBypassCodeOutHash:(NSString**)outHash { #define RANDOM_BYTES_LENGTH 16 #define SALT_LENGTH 4     // Encode raw bytes.     static const char kSymbols[] = "0123456789ACDEFGHJKLMNPQRTUVWXYZ";                                 //  00000000000000001111111111111111                                 //  0123456789abcdef0123456789abcdef

// Insert dashes after outputting characters at these positions.     static const int kDashPositions[] = { 5, 10, 14, 18, 22 };

char    rawBytes[MCBYPASS_RAW_BYTES_LENGTH];     char    code[MCBYPASS_CODE_BUFFER_LENGTH];     uint8_t hash[MCBYPASS_HASH_LENGTH];     uint8_t salt[SALT_LENGTH] = {0, 0, 0, 0};

arc4random_buf(rawBytes, RANDOM_BYTES_LENGTH);     CCKeyDerivationPBKDF(kCCPBKDF2, rawBytes, RANDOM_BYTES_LENGTH, salt, SALT_LENGTH,          kCCPRFHmacAlgSHA256, 50000, hash, CC_SHA256_DIGEST_LENGTH);

if (outHash) {         int                 len = MCBYPASS_HASH_LENGTH;         NSMutableString*    str = [NSMutableString stringWithCapacity:MCBYPASS_HASH_LENGTH * 2 + 1];         const uint8_t*      p   = (const uint8_t*)hash;         while (len-- > 0) [str appendFormat:@"%02X", *p++];         *outHash = [NSString stringWithString:str];     }

int         outputCharacterCount = 0;     const int*  nextDashPosition     = kDashPositions;     char*       outputCursor         = code;     uint8_t*    inputCursor          = (uint8_t*)rawBytes;

// Generate output one symbol at a time. #define INPUT_BITS      128 #define BITS_PER_BYTE   8 #define BITS_PER_SYMBOL 5

int bitsProcessed     = 0;     int bitOffsetIntoByte = 0;     while (bitsProcessed <= (INPUT_BITS - BITS_PER_SYMBOL)) {         int bitsThisByte = (bitOffsetIntoByte < BITS_PER_BYTE - BITS_PER_SYMBOL              ? BITS_PER_SYMBOL : BITS_PER_BYTE - bitOffsetIntoByte);         int bitsNextByte = (bitsThisByte < BITS_PER_SYMBOL ? BITS_PER_SYMBOL              - bitsThisByte : 0);

uint8_t value = (((*inputCursor << bitOffsetIntoByte) & 0xff)          >> (BITS_PER_BYTE - bitsThisByte));

bitOffsetIntoByte += BITS_PER_SYMBOL;         if (bitOffsetIntoByte >= BITS_PER_BYTE) {             bitOffsetIntoByte -= BITS_PER_BYTE;             inputCursor++;         }

if (bitsNextByte) {             value <<= bitsNextByte;             value |= (*inputCursor >> (BITS_PER_BYTE - bitsNextByte));         }

*outputCursor++ = kSymbols[value];         if (++outputCharacterCount == *nextDashPosition) {             ++nextDashPosition;             *outputCursor++ = '-';         }

bitsProcessed += BITS_PER_SYMBOL;     }

// Process remaining bits.     int bitsRemaining = INPUT_BITS - bitsProcessed;     if (bitsRemaining) {         uint8_t value = (((*inputCursor << bitOffsetIntoByte) & 0xff)              >> (BITS_PER_BYTE - bitsRemaining));        *outputCursor++ = kSymbols[value];     }     *outputCursor = '\0';     return [NSString stringWithUTF8String:code]; } // -_createNewActivationLockBypassCodeOutHash:

Use a bypass code to disable Activation Lock To remove Activation Lock, provide the deviceʼs bypass code to the web service as its escrowKey. The request needs to be a standard HTTPS POST on port 443 to https://deviceservices-external.apple.com/deviceservicesworkers/escrowKeyUnlock, and your device management service must provide its APNs certificate when establishing the SSL connection with the web service. The request must also have application/x-www-form-urlencoded as its contentType header. You must provide the following arguments as part of the URL request string:  |   |   |   |   |   |  You can obtain the IMEI values from the results of a DeviceInformationCommand with a ServiceSubscriptions query. Use the IMEI and MEID values for a Slot value of CTSubscriptionSlotOne for the imei and meid arguments, respectively. For the imei2 value, use the IMEI value (if any) for a Slot value of CTSubscriptionSlotTwo. Note that the server might ignore any MEID value that CTSubscriptionSlotTwo reports — this request only requires the first MEID, even for devices that have two IMEIs. Include the following arguments in the message body:  |   |   |   |
