a Myth That Won't Die

Embed Size (px)

Citation preview

  • 8/8/2019 a Myth That Won't Die

    1/9http://osxbook.com/book/bonus/chapter7/tpmdrmmyth/ Page 1

    "TPM DRM" In Mac OS X: A Myth That Won't Die 01/16/10 02:37 p.

    Written inDecember 2007

    the book

    Preface

    Table of Contents

    Read Reviews

    Source Code

    Errata

    Buy Now

    the book extras

    Bonus Content

    FAQ

    software

    Downloads

    Bug Reports

    meta

    Blog

    Forums

    Home

    about

    About the Author

    Rsum

    Contact

    elsewhere

    kernelthread.com

    adsense

    Google Search

    "TPM DRM" In Mac OS X: A Myth That Won'tDie

    Amit Singh. All Rights Reserved.

    Beating a Dead HorseApple began shipping x86-based Macintosh computers in early 2006. Even before that,

    people had noted the presence of a Trusted Platform Module (TPM) in the prerelease

    Developer Transition Kit machines. There had been much talk and much furor about the

    system-wide "DRM" the TPM would enforce. However, the x86-based Macintoshes were

    released with the TPM being not usedfor anything.

    In October 2006, I wrote about the TPM and its "use" in Mac OS X. Since Apple provided no

    software or firmware drivers for the TPM, I also wrote and released an open-source TPM

    driver for Mac OS X. In particular, I said the following.

    "Apple's TPM Keys"

    The media has been discussing "Apple's use of TPM" for a long time now. There havebeen numerous reports of system attackers bypassing "Apple's TPM protection" and

    finding "Apple's TPM keys."Nevertheless, it is important to note that Apple does not

    use the TPM. If you have a TPM-equipped Macintosh computer, you can use the TPM

    for its intended purpose, with no side effect on the normal working of Mac OS X.

    This turned out to be rather hard for many to believe. After all, Apple was somehow tying

    Mac OS X to their own hardware; and the early x86 Macs did have onboard TPMs. Some

    people concludedincorrectly sothat the TPM mustbe involved. As is often the norm on

    the Internet, such conclusions transmogrified into infallible myths. I found the nonsense

    rather hard to believeI had expected the open-source TPM driver to dispel such myths.

    The driver and associated software allowed the user to do "whatever" with the TPM: enable

    it, use it for their own purposes, even disable itwithout affecting the normal functioning of

    Mac OS X. Besides, the TPM was a common piece of hardware in modern-day computers,

    and indeed, it often sat unused in computers from several vendors. In the summer of 2006,when the Mac Pro was introduced, x86-based Macs stopped having onboard TPMs

    altogether. Even then, conspiracy theorists still came up with explanations, as they now

    concluded that the TPM somehow must have been incorporated with the CPU.

    Around the same time in 2006, I also wrote about kernel-level binary protection in Mac OS

    X. As that article explains, it is actually binary protection that ties Mac OS X to a specific

    class of hardware. The mechanism is partly implemented as a special-purpose virtual

    memory (VM) pager that is interposed between the kernel's higher layer and the vnode

    pager.

    Nevertheless, to this day, the myth continues. The TPM, although uninvolved in any Mac-

    related DRM (and non-existent in Macs for a long while now), often ends up being cannon

    fodder in Mac-related religious warfare.

    The Key to Understanding: Simple Minded Calculations

    So what's missing from the popular understanding of this issue? The keys to understanding

    how it works are all there in the aforementioned articles on TPM and binary protection. Well,

    almost all there. There's the small matter of the "key". Since we are talking about binary

    http://osxbook.com/contact/http://osxbook.com/blog/http://osxbook.com/software/bugs/http://osxbook.com/software/http://osxbook.com/book/buy/http://osxbook.com/http://osxbook.com/http://osxbook.com/http://osxbook.com/http://osxbook.com/http://osxbook.com/http://osxbook.com/http://osxbook.com/http://osxbook.com/http://osxbook.com/http://osxbook.com/http://osxbook.com/http://osxbook.com/book/bonus/chapter7/binaryprotection/http://osxbook.com/book/bonus/chapter10/tpm/http://osxbook.com/book/bonus/chapter7/binaryprotection/http://osxbook.com/book/bonus/chapter10/tpm/http://www.kernelthread.com/http://osxbook.com/contact/http://osxbook.com/resume/http://osxbook.com/about/http://osxbook.com/http://osxbook.com/forums/http://osxbook.com/blog/http://osxbook.com/software/bugs/http://osxbook.com/software/http://osxbook.com/book/faq/http://osxbook.com/book/bonus/http://osxbook.com/book/buy/http://osxbook.com/book/errata/http://osxbook.com/book/src/http://osxbook.com/book/reviews/http://osxbook.com/book/toc/http://osxbook.com/book/preface/
  • 8/8/2019 a Myth That Won't Die

    2/9http://osxbook.com/book/bonus/chapter7/tpmdrmmyth/ Page 2

    "TPM DRM" In Mac OS X: A Myth That Won't Die 01/16/10 02:37 p.

    encryption, what about the key to decrypt? I've been often asked about the nature of this

    keyin particular, where does it come from?

    Well, the key itself wasn't so interesting to me since I'm not allergic to Apple hardware.

    However, not knowing this bit of information seems to have led some to the "logical"

    conclusion that the key must be held within the... TPM! Perhaps the TPM that's "inside the

    CPU"? Except that there's no such thing. Ironically, it appears that even those who initially

    subverted Mac OS X to intercept the keys believed them to be "TPM keys".

    My interest in this is no different from my academic interest in the working of Mac OS X.

    The same interest had led to Mac OS X Internals, whose goal was to answer many, many

    questions. Here, we have a case where the wrong answer has taken a life of its own. I can't

    help but find such semi-wilful ignorance annoying.

    What isthe correct answer?

    The key (actually, a pair of 32-byte values) comes from the System Management Controller

    (SMC). Unlike in the case of a TPM, accessing this key involves no cryptography, no random

    numbers, no hardware securityit's merely obfuscation. Just as you can use I/O Kit

    interfaces to retrieve motion sensor data and numerous other readings from the SMC, you

    can retrieve the keyno number crunching involved. You don't even need superuser

    privileges. In fact, assuming you know how to access hardware from user-space, a program

    to do this would be quite straightforward to write on Mac OS Xperhaps around 50 lines of

    C.

    Figure 1 shows such a program.

    Why Obfuscate?

    I view the obfuscation approach as engineering pragmaticism in solving difficult

    problems. The problem here was that of making Mac OS X reasonably difficult to

    deploy (from a legal standpointthat is, would involve reverse engineering, breaking

    the EULA, etc.) on non-Apple hardware. A solution based on the TPM would have been

    fraught with numerous problems for the developers and maintainers of the solution.

    As is not uncommon in such cases, obfuscation can be an effective enough solution.

    /** smc_read.c: Written for Mac OS X 10.5. Compile as follows:** gcc -Wall -o smc_read smc_read.c -framework IOKit*/

    #include#include#include#include

    typedeftypedefstructstruct{uint32_t key;uint8_t __d0[22];uint32_t datasize;uint8_t __d1[10];uint8_t cmd;uint32_t __d2;uint8_t data[32];

    } AppleSMCBuffer_t;

    int

    mainmain(void){

    io_service_t service =IOServiceGetMatchingServiceIOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatchingIOServiceMatching("AppleSMC")); ifif(!service) returnreturn-1;

    io_connect_t port =(io_connect_t)0;

    http://docs.info.apple.com/article.html?artnum=303319http://osxbook.com/
  • 8/8/2019 a Myth That Won't Die

    3/9http://osxbook.com/book/bonus/chapter7/tpmdrmmyth/ Page 3

    "TPM DRM" In Mac OS X: A Myth That Won't Die 01/16/10 02:37 p.

    _ _ _ _kern_return_t kr =IOServiceOpenIOServiceOpen(service,mach_task_selfmach_task_self(),0,&port);

    IOObjectReleaseIOObjectRelease(service); ifif(kr != kIOReturnSuccess) returnreturn kr;

    AppleSMCBuffer_t inputStruct ={'OSK0',{0},32,{0},5,}, outputStruct;size_t outputStructCnt =sizeofsizeof(outputStruct);

    kr =IOConnectCallStructMethodIOConnectCallStructMethod((mach_port_t)port,(uint32_t)2, (constconstvoid*)&inputStruct,sizeofsizeof(inputStruct), (void*)&outputStruct,&outputStructCnt); ifif(kr != kIOReturnSuccess) returnreturn kr;

    int i =0; forfor(i =0; i

  • 8/8/2019 a Myth That Won't Die

    4/9http://osxbook.com/book/bonus/chapter7/tpmdrmmyth/ Page 4

    "TPM DRM" In Mac OS X: A Myth That Won't Die 01/16/10 02:37 p.

    #include#include

    #include#include

    #include#include

    #define#defineAPB_UNPROTECTED_HEADER_SIZEAPB_UNPROTECTED_HEADER_SIZE (3* PAGE_SIZE)#define#defineAPB_CRYPT_AES_KEY_SIZEAPB_CRYPT_AES_KEY_SIZE (256)#define#defineAPB_FAT_MAX_ARCHAPB_FAT_MAX_ARCH (5)

    staticstaticchar header_page[PAGE_SIZE];staticstaticchar data_page[PAGE_SIZE];staticstaticchar xcrypted_page[PAGE_SIZE];

    staticstatic boolean_t apb_initializeapb_initialize(int, AES_KEY*, AES_KEY*);staticstaticint apb_encrypt_pageapb_encrypt_page(constconstvoid*,void*);

    staticstatic io_connect_t AppleSMC_ConnectAppleSMC_Connect(void);staticstaticvoid AppleSMC_DisconnectAppleSMC_Disconnect(io_connect_t);staticstatic IOReturn AppleSMC_Read32AppleSMC_Read32(io_connect_t, uint32_t, uint8_t*);

    typedeftypedefstructstruct{uint32_t key;uint8_t __d0[22];uint32_t datasize;uint8_t __d1[10];uint8_t cmd;uint32_t __d2;uint8_t data[32];

    } AppleSMCBuffer_t;

    staticstatic io_connect_tAppleSMC_ConnectAppleSMC_Connect(void){

    io_connect_t port =(io_connect_t)0;

    io_service_t service =IOServiceGetMatchingServiceIOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatchingIOServiceMatching("AppleSMC")); ifif(!service){ returnreturn port; }

    kern_return_t kr =IOServiceOpenIOServiceOpen(service,mach_task_selfmach_task_self(),0,&port); IOObjectReleaseIOObjectRelease(service);

    ifif(kr != kIOReturnSuccess){ returnreturn(io_connect_t)0; }

    returnreturn port;}

    staticstaticvoidAppleSMC_DisconnectAppleSMC_Disconnect(io_connect_t port)

    { (void)IOServiceCloseIOServiceClose(port);}

    staticstatic IOReturnAppleSMC_Read32AppleSMC_Read32(io_connect_t port, uint32_t key, uint8_t* data32){

    AppleSMCBuffer_t inputStruct ={0,{0},32,{0},5,};AppleSMCBuffer_t outputStruct;size_t outputStructCnt =sizeofsizeof(outputStruct);

    inputStruct.key = key;

    IOReturn kr =IOConnectCallStructMethodIOConnectCallStructMethod((mach_port_t)port,(uint32_t)2, (constconstvoid*)&inputStruct,sizeofsizeof(inputStruct), (void*)&outputStruct,&outputStructCnt); ifif(kr != kIOReturnSuccess){ returnreturn kr; }

    (void)memcpymemcpy(data32, outputStruct.data,32);

    returnreturn kIOReturnSuccess;}

    staticstatic boolean_tapb_initializeapb_initialize(__unused int mode, AES_KEY* key1, AES_KEY* key2){

    boolean_t result = FALSE;

  • 8/8/2019 a Myth That Won't Die

    5/9http://osxbook.com/book/bonus/chapter7/tpmdrmmyth/ Page 5

    "TPM DRM" In Mac OS X: A Myth That Won't Die 01/16/10 02:37 p.

    _

    io_connect_t port =AppleSMC_ConnectAppleSMC_Connect(); ifif(!port){ returnreturn result; }

    IOReturn ret;uint8_t data32[32]={0};

    ret =AppleSMC_Read32AppleSMC_Read32(port,'OSK0', data32); ifif(ret != kIOReturnSuccess){ gotogoto out; }

    AES_set_encrypt_keyAES_set_encrypt_key(data32, APB_CRYPT_AES_KEY_SIZE, key1);

    ret =AppleSMC_Read32AppleSMC_Read32(port,'OSK1', data32); ifif(ret != kIOReturnSuccess){ gotogoto out; } AES_set_encrypt_keyAES_set_encrypt_key(data32, APB_CRYPT_AES_KEY_SIZE, key2);

    result = TRUE;

    out: AppleSMC_DisconnectAppleSMC_Disconnect(port);

    returnreturn result;}

    staticstaticintapb_encrypt_pageapb_encrypt_page(constconstvoid* in,void* out){ staticstatic AES_KEY key1, key2; staticstatic boolean_t initialized = FALSE;

    ifif(initialized == FALSE){initialized =apb_initializeapb_initialize(AES_ENCRYPT,&key1,&key2);

    ifif(initialized == FALSE){ returnreturn-1; } }

    constconstunsignedchar* _in =(constconstunsignedchar*)in; unsignedchar* _out =(unsignedchar*)out;

    unsignedchar apb_null_iv1[AES_BLOCK_SIZE]={0x0,}; unsignedchar apb_null_iv2[AES_BLOCK_SIZE]={0x0,};

    AES_cbc_encryptAES_cbc_encrypt(_in, _out, PAGE_SIZE /2,&key1, apb_null_iv1, AES_ENCRYPT);_in +=(PAGE_SIZE /2);_out +=(PAGE_SIZE /2);

    AES_cbc_encryptAES_cbc_encrypt(_in, _out, PAGE_SIZE /2,&key2, apb_null_iv2, AES_ENCRYPT);

    returnreturn0;

    }intmainmain(int argc,char** argv){ int fd_in =-1; int fd_out =-1;

    ifif(argc !=3){ fprintffprintf(stderr,"usage: %s \n", argv[0]); exitexit(1); }

    fd_in =openopen(argv[1], O_RDONLY); ifif(fd_in

  • 8/8/2019 a Myth That Won't Die

    6/9http://osxbook.com/book/bonus/chapter7/tpmdrmmyth/ Page 6

    "TPM DRM" In Mac OS X: A Myth That Won't Die 01/16/10 02:37 p.

    }

    uint32_t magic =*(uint32_t*)header_page; structstructmach_header* mh =(structstructmach_header*)0;

    #ifdef#ifdef __LITTLE_ENDIAN__ ifif(magic == FAT_CIGAM){ structstructfat_header* fh =(structstructfat_header*)header_page;

    uint32_t nfat_arch =ntohlntohl(fh->nfat_arch); ifif(nfat_arch > APB_FAT_MAX_ARCH){ fprintffprintf(stderr,"too many architectures in Universal binary\n");

    ret =-1; gotogoto out;

    } structstructfat_arch* fa =(structstructfat_arch*)((char*)header_page + sizeofsizeof(structstructfat_header)); forfor(n =0; n < nfat_arch; n++, fa++){ ifif(ntohlntohl(fa->cputype)== CPU_TYPE_X86){

    base =(off_t)ntohlntohl(fa->offset);nbytes =preadpread(fd_in, header_page, PAGE_SIZE, base);

    ifif(nbytes != PAGE_SIZE){ fprintffprintf(stderr,"failed to read Universal binary\n");

    ret =-1; gotogoto out; }

    mh =(structstructmach_header*)header_page; breakbreak; } } }elseelseifif(magic == MH_MAGIC){

    mh =(structstructmach_header*)header_page; ifif(mh->cputype != CPU_TYPE_X86){ fprintffprintf(stderr,"this program supports only x86 architecture\n");

    ret =-1;

    gotogoto out; } }elseelse{ fprintffprintf(stderr,"not an appropriate Mach-O file\n");

    ret =-1; gotogoto out; }#else#else#error#error This file can only be compiled on Intel.#endif#endif

    structstructsegment_command* text =(structstructsegment_command*)0;

    uint32_t ncmds = mh->ncmds; structstructload_command* lc = (structstructload_command*)((char*)mh +sizeofsizeof(structstructmach_header));

    forfor(n =0; n < ncmds; n++){ ifif(lc->cmd == LC_SEGMENT){ structstructsegment_command* sc =(structstructsegment_command*)lc;

    ifif(strcmpstrcmp(sc->segname, SEG_TEXT)==0){text = sc; breakbreak; } }

    lc =(structstructload_command*)((char*)lc + lc->cmdsize); }

    ifif(!text){ fprintffprintf(stderr,"failed to find text segment\n");

    ret =-1; gotogoto out; }

    ifif(text->flags & SG_PROTECTED_VERSION_1){ fprintffprintf(stderr,"already encrypted\n");

    ret =-1; gotogoto out; }

    ifif(text->filesize < APB_UNPROTECTED_HEADER_SIZE){

    fprintffprintf(stderr,"text segment is too small to protect\n");ret =-1; gotogoto out; }

    off_t archbase_begin =(off_t)(text->fileoff + APB_UNPROTECTED_HEADER_SIZE);off_t archbase_end =

    archbase_begin +(off_t)(text->filesize - APB_UNPROTECTED_HEADER_SIZE);

  • 8/8/2019 a Myth That Won't Die

    7/9http://osxbook.com/book/bonus/chapter7/tpmdrmmyth/ Page 7

    "TPM DRM" In Mac OS X: A Myth That Won't Die 01/16/10 02:37 p.

    _ _ _ _ _

    ebase_begin = base + archbase_begin;ebase_end = base + archbase_end;

    fd_out =openopen(argv[2], O_RDWR | O_CREAT | O_EXCL,0755); ifif(fd_out flags |= SG_PROTECTED_VERSION_1;

    nbytes =pwritepwrite(fd_out, header_page, PAGE_SIZE, base); ifif(nbytes != PAGE_SIZE){ perrorperror("pwrite");

    ret =-1; gotogoto out; }

    off_t count = ebase_end - ebase_begin; ifif(count % PAGE_SIZE){ fprintffprintf(stderr,"text segment not a multiple of page size\n");

    ret =-1; gotogoto out; }

    whilewhile(count >0){nbytes =preadpread(fd_in, data_page, PAGE_SIZE, ebase_begin);

    ifif(nbytes != PAGE_SIZE){ perrorperror("pread");

    ret =-1; gotogoto out; }

    ret =apb_encrypt_pageapb_encrypt_page(data_page, xcrypted_page); ifif(ret){ fprintffprintf(stderr,"failed to encrypt page\n"); gotogoto out; }

    nbytes =pwritepwrite(fd_out, xcrypted_page, PAGE_SIZE, ebase_begin); ifif(nbytes != PAGE_SIZE){ perrorperror("pwrite");

    ret =-1; gotogoto out; }

    ebase_begin +=(off_t)PAGE_SIZE;count -=(off_t)PAGE_SIZE;

    }ret =0;

    out: ifif(fd_in >=0){ closeclose(fd_in); } ifif(fd_out >=0){ closeclose(fd_out); ifif(ret){ unlinkunlink(argv[2]); } }

    exitexit(ret);}

    Figure 2. Creating a protected binary

    Let us look at our encryption program in action. Recall from the binary protection

    discussion that the LC_SEGMENT load command for an encrypted segment has a special bit

    (0x8) set. In that discussion, we used the otool command-line program to view the load

    commands in a Mach-O file. Figure 3 shows an excerpt from the output of running otool

    on the binaries for ls and the Finder. We see that the flags field has the 0x8 bit set in the

    Finder's case, which is a protected binary, but not in the case ofls .

    http://osxbook.com/book/bonus/chapter7/binaryprotection/
  • 8/8/2019 a Myth That Won't Die

    8/9http://osxbook.com/book/bonus/chapter7/tpmdrmmyth/ Page 8

    "TPM DRM" In Mac OS X: A Myth That Won't Die 01/16/10 02:37 p.

    $ otool -l /bin/ls/bin/ls:Load command 0

    ...Load command 1

    cmd LC_SEGMENTcmdsize 260segname __TEXTvmaddr 0x00001000vmsize 0x00005000

    fileoff 0filesize 20480

    maxprot 0x00000007initprot 0x00000005nsects 3

    flags 0x0Section

    ...

    $ cd /System/Library/CoreServices/Finder.app/Contents/MacOS$ otool -l FinderFinder:Load command 0

    ...Load command 1

    cmd LC_SEGMENTcmdsize 668segname __TEXTvmaddr 0x00001000vmsize 0x00404000

    fileoff 0filesize 4210688maxprot 0x00000007

    initprot 0x00000005nsects 9

    flags 0x8Section

    ...

    Figure 3. Using otool to view Mach-O load commands

    Let us now create a protected copy of ls . Figure 4 shows a sequence of commands to do

    that assuming you've downloaded apb_encrypt.c to /tmp/.

    $ cd /tmp

    $ gcc -Wall -o apb_encrypt apb_encrypt.c -framework IOKit -lcrypto$ cp /bin/ls ./ls$ ./apb_encrypt ls ls.protected$ ls -l ls*total 288144 -r-xr-xr-x 1 you wheel 73696 Jan 31 22:52 ls144 -r-xr-xr-x 1 you wheel 73696 Jan 31 22:54 ls.protected$ diff ls ls.protectedBinary files ls and ls.protected differ$ otool -l ls.protected

    ...Load command 1

    cmd LC_SEGMENTcmdsize 260segname __TEXTvmaddr 0x00001000vmsize 0x00005000

    fileoff 0filesize 20480maxprot 0x00000007

    initprot 0x00000005

    nsects 3 flags 0x8Section

    ...$ strings ls...usage: ls [-ABCFGHLPRSTWabcdefghiklmnopqrstuwx1] [file ...]humanize_numberbuf != NULLhumanize_number.csuffix != NULL...$ strings ls.protected...q9D@J[19:Jk#.Wnu`=SI...$ otool -t -v -V ls.protected | grep 'bad opcode'...0000510c .byte 0xb2 #bad opcode000051b9 .byte 0xf1 #bad opcode000051c8 .byte 0x8e #bad opcode000051f1 .byte 0x77 #bad opcode...$ ./ls.protected -l

  • 8/8/2019 a Myth That Won't Die

    9/9http://osxbook com/book/bonus/chapter7/tpmdrmmyth/ Page 9

    "TPM DRM" In Mac OS X: A Myth That Won't Die 01/16/10 02:37 p.

    total 288-r-xr-xr-x 1 you wheel 73696 Jan 31 22:52 ls-r-xr-xr-x 1 you wheel 73696 Jan 31 22:54 ls.protected

    Our protected version ofls is automagically decrypted at runtime by the operating system.

    Ifyou're so inclined, you could even encrypt your entire system (!) this way with your own

    keys. Of course, you'd have to re-encrypt the system's apple-protected binaries with your

    own keys too, and write a kernel extension that sets your keys up as the ones to be used by

    the operating system. You'll then have a system unlike any other. (Don't do itI wasn't

    being serious.)

    All contents of this site, unless otherwise noted, are 1994-2010 Amit Singh. All Rights Reserved. Terms of Use

    http://osxbook.com/legalese/