commit 0155b2098eeb591fa4e558a4a79993c6e067f3ec
Author: 3DSGuy <3dsguy.dev@gmail.com>
Date: Sun Feb 16 16:55:00 2014 +0800
makerom v0.1
diff --git a/Application.desc b/Application.desc
new file mode 100644
index 0000000..b3a6094
--- /dev/null
+++ b/Application.desc
@@ -0,0 +1,258 @@
+AccessControlInfo:
+ AffinityMask: 1
+ AutoGen: true
+ CoreVersion: 2
+ DescVersion: 2
+ Descriptor: |
+ AP///wAABAACAAAAAAAFGJ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIAAAAAAAABBUFQ6VQAAACRo
+ aW9GSU8AJGhvc3RpbzAkaG9zdGlvMWFjOnUAAAAAYm9zczpVAABjYW06dQAA
+ AGNlY2Q6dQAAY2ZnOnUAAABkbHA6RktDTGRscDpTUlZSZHNwOjpEU1BmcmQ6
+ dQAAAGZzOlVTRVIAZ3NwOjpHcHVoaWQ6VVNFUmh0dHA6QwAAbWljOnUAAABu
+ ZG06dQAAAG5ld3M6dQAAbndtOjpVRFNwdG06dQAAAHB4aTpkZXYAc29jOlUA
+ AABzc2w6QwAAAHkycjp1AAAAbGRyOnJvAABpcjpVU0VSAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAABOn/rw/7//8ec/APIA8JH/APaR/1D/gf9Y/4H/cP+B/3j/gf8B
+ AQD/AAIA/iECAPz/////////////////////////////////////////////
+ ////////////////////////////////////////AAAAAAAAAAAAAAAAAAAA
+ AAADAAAAAAAAAAAAAAAAAAI=
+ DisableDebug: false
+ EnableInterruptNumbers:
+ EnableSystemCalls:
+ ArbitrateAddress: 34
+ Break: 60
+ CancelTimer: 28
+ ClearEvent: 25
+ ClearTimer: 29
+ CloseHandle: 35
+ ConnectToPort: 45
+ ControlMemory: 1
+ CreateAddressArbiter: 33
+ CreateEvent: 23
+ CreateMemoryBlock: 30
+ CreateMutex: 19
+ CreateSemaphore: 21
+ CreateThread: 8
+ CreateTimer: 26
+ DuplicateHandle: 39
+ ExitProcess: 3
+ ExitThread: 9
+ GetCurrentProcessorNumber: 17
+ GetHandleInfo: 41
+ GetProcessId: 53
+ GetProcessIdOfThread: 54
+ GetProcessIdealProcessor: 6
+ GetProcessInfo: 43
+ GetResourceLimit: 56
+ GetResourceLimitCurrentValues: 58
+ GetResourceLimitLimitValues: 57
+ GetSystemInfo: 42
+ GetSystemTick: 40
+ GetThreadContext: 59
+ GetThreadId: 55
+ GetThreadIdealProcessor: 15
+ GetThreadInfo: 44
+ GetThreadPriority: 11
+ MapMemoryBlock: 31
+ OutputDebugString: 61
+ QueryMemory: 2
+ ReleaseMutex: 20
+ ReleaseSemaphore: 22
+ SendSyncRequest1: 46
+ SendSyncRequest2: 47
+ SendSyncRequest3: 48
+ SendSyncRequest4: 49
+ SendSyncRequest: 50
+ SetThreadPriority: 12
+ SetTimer: 27
+ SignalEvent: 24
+ SleepThread: 10
+ UnmapMemoryBlock: 32
+ WaitSynchronization1: 36
+ WaitSynchronizationN: 37
+ FileSystemAccess:
+ - Debug
+ - DirectSdmc
+ - DirectSdmcWrite
+ HandleTableSize: 512
+ IORegisterMapping:
+ - 1ff50000-1ff57fff
+ - 1ff70000-1ff77fff
+ IdealProcessor: 1
+ IoAccessControl:
+ - UseDirectSdmc
+ - SdApplication
+ MemoryMapping:
+ - 1f000000-1f5fffff:r
+ MemoryType: Application
+ Priority: 24
+ ProgramId: 0x00040000ffffff00L
+ ReleaseKernelMajor: "02"
+ ReleaseKernelMinor: "33"
+ ServiceAccessControl:
+ - APT:U
+ - $hioFIO
+ - $hostio0
+ - $hostio1
+ - ac:u
+ - boss:U
+ - cam:u
+ - cecd:u
+ - cfg:u
+ - dlp:FKCL
+ - dlp:SRVR
+ - dsp::DSP
+ - frd:u
+ - fs:USER
+ - gsp::Gpu
+ - hid:USER
+ - http:C
+ - mic:u
+ - ndm:u
+ - news:u
+ - nwm::UDS
+ - ptm:u
+ - pxi:dev
+ - soc:U
+ - ssl:C
+ - y2r:u
+ - ldr:ro
+ - ir:USER
+ Signature: |
+ 3xyLmORvojVswxgXmPPOVH4ULn8e2G3PvClO/jIuwRGtRprGcOruKFUi4TYF
+ HASKzg8Mg4/I1t4RjurPrZvPgQ3rcROz066DAkwOEFBZPO5gBvuMf8IgJAFi
+ VYdgD636cy72ZWLS5RBFaXA5A9E57FDB1CU5spARTpXLGevKD7X6x7Di1+Bx
+ w+VVM55c3E07URENMXiWytcYWO4A6SjyaHbUV/5lsUtJP/amWErH/MS7YbxY
+ jVVl5gp5OUG4gGH3BcP+1osJgsJfplb57h0OBj6fP/GTmk+i1ZGHiv7Pw/yK
+ scR46dEa97HTIMuDvgPVyqVeF6aRENS+I9ZLTwOprg==
+ StorageId:
+ - 0
+CommonHeaderKey:
+ D: |
+ jL2yO86eUQnYbXIrzgFVMm7FVze0LglZ2f5g+c42hWoEdnb5BOotaMQPBfqt
+ aUyAEmzQPaoi/4l4V+hTJRXQfthVRqIEx27B84l8LA6Tl5Fy9PaQaQ+4yRfP
+ g6ylH2l0EikrIVjy2uMlFgl0QJCrG+QGKHftxhaGCifdAwFNmiZuyJ/TmktZ
+ 0RCb66lYcr2h/p2G7SnpKUliS9h9KnpmG+UEgVYQUK+4SCfByUa9PxYGpT0E
+ nw1UcRz0gsBmdOqcgzwnAd9vVqgb42hVn6uQZyAl+j1RKiMWywZarazIR/k5
+ Lmr4+groimSEa+3ajyoIho9WaWTDmFU3mkhA2tUDIQ==
+ DP: |
+ pD8c9uymjXDj6oyhx7EmQcrEDizxsj6hTjJ0x3G/PYNv/v2/DA9gp3X30h35
+ uRZ1O+SgonWCGVnOJ7Wfjr4w2cOcSzxpzT3PQsS6Gs9z0RvcDsUHRL5f2EiT
+ 6A1ZPj6xyzmo9Ts6w9yfxCwaHci0f2hP9bq9FimfFKigCoNcFBE=
+ DQ: |
+ y+6Pado7N+SIZJgQ7zEGyQ7/SxGHHEy5uW04HHde9IqHD5HFGG2GegF655mM
+ iI9ja1eTCh/AFs8xjAg0drQEvB5q80TjPNKtwVUT8ghOlN3xTzpdaLwX0d+c
+ Twy74VY4KPawcdDeLaGFtXknhFOdGmIbx+BInibz7NZ9eLqGwaE=
+ Exponent: |
+ AQAB
+ InverseQ: |
+ tc9/lcF837g8AdfyeuCyuLyd36Zm1ZmJ1VSSuH8y3/1ZhBYZkOFXxU7EhMvJ
+ FyAu4qyCA9otzCXM+cqKxE3ZCkSconsXOu8szZTwuINSkwHlt22FtiTfPt+V
+ /g5kjtkjoZVOGfSvvfel9Smwy1yrFvKfi/yJsjATeNFjiEquV/w=
+ Modulus: |
+ z+yySANtuAnjXGxiLKlJ4fT0DGzD5S+dUKArWgDGcgALowRdlEbnABtIhbVh
+ LMl0yitDE8F4l1wzLwfHhfDa22CWUA98S3rXF53k5cOrb12leDKtBN2Wbtx1
+ /8Iv+qLuRonNrmmSpEi8RkfEjIlj4QpNHNxGL1twinzpIpwJC6iXQMoqfYSh
+ BEou29fQZEOc0HgRQYgz3TFikC0X8sapK5xwq9zTq13a7j1sDoH/9mdaRPms
+ Bz0jlHVlkyAMxXYdD2UGPSGi8JaAtwpJUzijXcB0PKTZQDaFH4zRLRX57ySp
+ fp2yHvigcoEXd3OxVn+tBaLSMFr1068PEEpS2AlHlw==
+ P: |
+ 6SdD3AiAybNamgUgGJduyFWO1/LeakmoJm+23IEJADyU4nz+reGjxQnMrR+x
+ syuB8VPGuf1z0SInfRIu9PEjIfW9/H/fZ59GwckQuJbneODjW7KU1jM3cTVX
+ +AWvaxWDwlCUmVSYD2OySUJlo3szGmBYh/o/tKAq7kElaaOt+cc=
+ Q: |
+ 5EyO8bCyfqgLTfipAG/nNLObQbqMyARdQfudxh4eQqHmzblEM3jareuA8eUZ
+ K8pIaP+U9UfxwWTeFsOulrpsm04j4gS71WGNx3YwOIRPXXOn7zBkxA3AO9qq
+ K8lMeV3gNsdt4Fz8Zh2F68HSP4avB+ThO2S18SXMyIkcM7Sbw7E=
+DefaultSpec:
+ AccessControlInfo:
+ ServiceAccessControl:
+ - APT:U
+ - $hioFIO
+ - $hostio0
+ - $hostio1
+ - ac:u
+ - boss:U
+ - cam:u
+ - cecd:u
+ - cfg:u
+ - dlp:FKCL
+ - dlp:SRVR
+ - dsp::DSP
+ - frd:u
+ - fs:USER
+ - gsp::Gpu
+ - hid:USER
+ - http:C
+ - mic:u
+ - ndm:u
+ - news:u
+ - nwm::UDS
+ - ptm:u
+ - pxi:dev
+ - soc:U
+ - ssl:C
+ - y2r:u
+ - ldr:ro
+ - ir:USER
+ AffinityMask: 1
+ FirmwareVersion: 2
+ HandleTableSize: 512
+ IORegisterMapping:
+ - 1ff50000-1ff57fff
+ - 1ff70000-1ff77fff
+ IdealProcessor: 0
+ MemoryMapping:
+ - 1f000000-1f5fffff:r
+ Priority: 16
+ BasicInfo:
+ CompanyCode: "00"
+ Logo: Nintendo
+ Title: default
+ ExeFs:
+ ReadOnly:
+ - RO
+ ReadWrite:
+ - RW
+ Text:
+ - STUP_ENTRY
+ PlainRegion:
+ - .module_id
+ Rom:
+ DefaultReject:
+ - .*
+ File:
+ - "*"
+ SystemControlInfo:
+ Dependency:
+ ac: 0x0004013000002402L
+ am: 0x0004013000001502L
+ boss: 0x0004013000003402L
+ camera: 0x0004013000001602L
+ cecd: 0x0004013000002602L
+ cfg: 0x0004013000001702L
+ codec: 0x0004013000001802L
+ csnd: 0x0004013000002702L
+ dlp: 0x0004013000002802L
+ dsp: 0x0004013000001a02L
+ friends: 0x0004013000003202L
+ gpio: 0x0004013000001b02L
+ gsp: 0x0004013000001c02L
+ hid: 0x0004013000001d02L
+ http: 0x0004013000002902L
+ i2c: 0x0004013000001e02L
+ ir: 0x0004013000003302L
+ mcu: 0x0004013000001f02L
+ mic: 0x0004013000002002L
+ ndm: 0x0004013000002b02L
+ news: 0x0004013000003502L
+ nim: 0x0004013000002c02L
+ nwm: 0x0004013000002d02L
+ pdn: 0x0004013000002102L
+ ps: 0x0004013000003102L
+ ptm: 0x0004013000002202L
+ ro: 0x0004013000003702L
+ socket: 0x0004013000002e02L
+ spi: 0x0004013000002302L
+ ssl: 0x0004013000002f02L
+ StackSize: 262144
diff --git a/Application.rsf b/Application.rsf
new file mode 100644
index 0000000..33d5aa0
--- /dev/null
+++ b/Application.rsf
@@ -0,0 +1,37 @@
+# Default value for application
+BasicInfo:
+ Title : "Homebrew"
+ CompanyCode : "00"
+ MediaSize : 128MB # 128MB / 256MB / 512MB / 1GB / 2GB
+ MediaFootPadding: false
+ ProductCode : "CTR-P-HAXX"
+ ContentType : Application # Application / SystemUpdate / Manual / Child / Trial
+ Logo : Nintendo # Nintendo / Licenced / Distributed
+ BackupMemoryType: None # None / 128KB / 512KB
+
+Rom:
+ # Specifies the root path of the file system to include in the ROM.
+ HostRoot: "$(ROMFS_ROOT)"
+ SaveDataSize: 512KB
+
+
+TitleInfo:
+ UniqueId: 1337
+ #TargetCategory: Contents
+ Category: Application
+ #DemoIndex: 1
+ Version: 0
+
+CardInfo:
+ #WritableAddress: 0x200
+ #CardType : S2 # S1 / S2
+ #CryptoType : 3 # 0 - 3
+ CardDevice : NorFlash # NorFlash(0), None(1), BT(2)
+ #MediaType : CARD1 # Card1 / Card2
+
+Option:
+ # ??????????????? true
+ UseOnSD: true # true if App is to be installed to SD
+ EnableCompress: true # true / false
+ FreeProductCode: true # true ???????????????????????
+ EnableCrypt : true # fasle ????????
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7289448
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,59 @@
+# Makerom Sources
+UTILS_OBJS = utils.o keyset.o titleid.o
+CIA_OBJS = cia.o certs.o tik.o tmd.o
+NCCH_OBJS = ncch.o exheader.o exefs.o elf.o romfs.o
+NCSD_OBJS = ncsd.o
+SETTINGS_OBJS = usersettings.o yamlsettings.o
+LIB_API_OBJS = crypto.o yaml_ctr.o blz.o
+
+OBJS = makerom.o $(UTILS_OBJS) $(LIB_API_OBJS) $(SETTINGS_OBJS) $(NCSD_OBJS) $(NCCH_OBJS) $(CIA_OBJS)
+
+# Libraries
+POLAR_OBJS = polarssl/aes.o polarssl/bignum.o polarssl/rsa.o polarssl/sha1.o polarssl/sha2.o polarssl/padlock.o polarssl/md.o polarssl/md_wrap.o polarssl/md2.o polarssl/md4.o polarssl/md5.o polarssl/sha4.o polarssl/base64.o polarssl/cipher.o polarssl/cipher_wrap.o polarssl/camellia.o polarssl/des.o polarssl/blowfish.o
+YAML_OBJS = libyaml/api.o libyaml/dumper.o libyaml/emitter.o libyaml/loader.o libyaml/parser.o libyaml/reader.o libyaml/scanner.o libyaml/writer.o
+
+# Compiler Settings
+LIBS = -static-libgcc -static-libstdc++
+CXXFLAGS = -I.
+CFLAGS = --std=c99 -Wall -I. -DMAKEROM_VER_MAJOR=$(VER_MAJOR) -DMAKEROM_VER_MINOR=$(VER_MINOR) $(MAKEROM_BUILD_FLAGS)
+CC = gcc
+
+# MAKEROM Build Settings
+MAKEROM_BUILD_FLAGS = -DPRIVATE_BUILD -DRETAIL_FSIGN -DELF_DEBUG
+VER_MAJOR = 0
+VER_MINOR = 1
+OUTPUT = makerom
+
+#
+main: build
+
+rebuild: clean build
+
+build: $(OBJS) $(POLAR_OBJS) $(YAML_OBJS)
+ g++ -o $(OUTPUT) $(LIBS) $(OBJS) $(POLAR_OBJS) $(YAML_OBJS)
+
+clean:
+ rm -rf $(OUTPUT) $(OBJS) $(POLAR_OBJS) $(YAML_OBJS) *.cci *.cia *.cxi *.cfa
+
+# Winfail compatibility
+rebuildwin: cleanwin build
+cleanwin:
+ del $(OUTPUT).exe *.o polarssl\*.o libyaml\*.o *.cci *.cia *.cxi *.cfa
+
+#Test Functions
+
+ccigen_sdk:
+ ctr_makerom32 -f card -rsf testdata\Application.rsf -o content_test_sdk.cci -content testdata\app_zeroskey.cxi:0 -content testdata\manual_zeroskey.cfa:1 -content testdata\dlp_zeroskey.cfa:2 -content testdata\update_zeroskey.cfa:7
+ del content_test_sdk.cci.xml
+
+ccigen:
+ $(OUTPUT) -f card -rsf testdata\Application.rsf -o content_test.cci -content testdata\app_zeroskey.cxi:0 -content testdata\manual_zeroskey.cfa:1 -content testdata\dlp_zeroskey.cfa:2 -content testdata\update_zeroskey.cfa:7
+
+ciagen_sdk:
+ ctr_makecia32 -o content_test.cia -i testdata\app_zeroskey.cxi:0 -i testdata\manual_zeroskey.cfa:1 -i testdata\dlp_zeroskey.cfa:2
+
+ciagen:
+ $(OUTPUT) -f cia -o content_test.cia -content testdata\app_zeroskey.cxi:0 -content testdata\manual_zeroskey.cfa:1 -content testdata\dlp_zeroskey.cfa:2 -encryptcia
+
+pyramids:
+ $(OUTPUT) -f cxi -accessdesc app -o pyramids.cxi -code pyramids\code.bin -exheader pyramids\exheader.bin -rsf pyramids\app.rsf -desc pyramids\build.desc -icon pyramids\icon.icn -banner pyramids\banner.bnr -romfs pyramids\romfs.bin
\ No newline at end of file
diff --git a/accessdesc_sig.h b/accessdesc_sig.h
new file mode 100644
index 0000000..327e5cc
--- /dev/null
+++ b/accessdesc_sig.h
@@ -0,0 +1,52 @@
+#ifndef _ACCESSDESC_SIG_H_
+#define _ACCESSDESC_SIG_H_
+
+// APP
+static const unsigned char App_HdrPubK[0x100] =
+{
+ 0xCF, 0xEC, 0xB2, 0x48, 0x03, 0x6D, 0xB8, 0x09, 0xE3, 0x5C, 0x6C, 0x62, 0x2C, 0xA9, 0x49, 0xE1, 0xF4, 0xF4, 0x0C, 0x6C, 0xC3, 0xE5, 0x2F, 0x9D, 0x50, 0xA0, 0x2B, 0x5A, 0x00, 0xC6, 0x72, 0x00, 0x0B, 0xA3, 0x04, 0x5D, 0x94, 0x46, 0xE7, 0x00, 0x1B, 0x48, 0x85, 0xB5, 0x61, 0x2C, 0xC9, 0x74, 0xCA, 0x2B, 0x43, 0x13, 0xC1, 0x78, 0x97, 0x5C, 0x33, 0x2F, 0x07, 0xC7, 0x85, 0xF0, 0xDA, 0xDB, 0x60, 0x96, 0x50, 0x0F, 0x7C, 0x4B, 0x7A, 0xD7, 0x17, 0x9D, 0xE4, 0xE5, 0xC3, 0xAB, 0x6F, 0x5D, 0xA5, 0x78, 0x32, 0xAD, 0x04, 0xDD, 0x96, 0x6E, 0xDC, 0x75, 0xFF, 0xC2, 0x2F, 0xFA, 0xA2, 0xEE, 0x46, 0x89, 0xCD, 0xAE, 0x69, 0x92, 0xA4, 0x48, 0xBC, 0x46, 0x47, 0xC4, 0x8C, 0x89, 0x63, 0xE1, 0x0A, 0x4D, 0x1C, 0xDC, 0x46, 0x2F, 0x5B, 0x70, 0x8A, 0x7C, 0xE9, 0x22, 0x9C, 0x09, 0x0B, 0xA8, 0x97, 0x40, 0xCA, 0x2A, 0x7D, 0x84, 0xA1, 0x04, 0x4A, 0x2E, 0xDB, 0xD7, 0xD0, 0x64, 0x43, 0x9C, 0xD0, 0x78, 0x11, 0x41, 0x88, 0x33, 0xDD, 0x31, 0x62, 0x90, 0x2D, 0x17, 0xF2, 0xC6, 0xA9, 0x2B, 0x9C, 0x70, 0xAB, 0xDC, 0xD3, 0xAB, 0x5D, 0xDA, 0xEE, 0x3D, 0x6C, 0x0E, 0x81, 0xFF, 0xF6, 0x67, 0x5A, 0x44, 0xF9, 0xAC, 0x07, 0x3D, 0x23, 0x94, 0x75, 0x65, 0x93, 0x20, 0x0C, 0xC5, 0x76, 0x1D, 0x0F, 0x65, 0x06, 0x3D, 0x21, 0xA2, 0xF0, 0x96, 0x80, 0xB7, 0x0A, 0x49, 0x53, 0x38, 0xA3, 0x5D, 0xC0, 0x74, 0x3C, 0xA4, 0xD9, 0x40, 0x36, 0x85, 0x1F, 0x8C, 0xD1, 0x2D, 0x15, 0xF9, 0xEF, 0x24, 0xA9, 0x7E, 0x9D, 0xB2, 0x1E, 0xF8, 0xA0, 0x72, 0x81, 0x17, 0x77, 0x73, 0xB1, 0x56, 0x7F, 0xAD, 0x05, 0xA2, 0xD2, 0x30, 0x5A, 0xF5, 0xD3, 0xAF, 0x0F, 0x10, 0x4A, 0x52, 0xD8, 0x09, 0x47, 0x97
+};
+
+static const unsigned char App_HdrPrivK[0x100] =
+{
+ 0x8C, 0xBD, 0xB2, 0x3B, 0xCE, 0x9E, 0x51, 0x09, 0xD8, 0x6D, 0x72, 0x2B, 0xCE, 0x01, 0x55, 0x32, 0x6E, 0xC5, 0x57, 0x37, 0xB4, 0x2E, 0x09, 0x59, 0xD9, 0xFE, 0x60, 0xF9, 0xCE, 0x36, 0x85, 0x6A, 0x04, 0x76, 0x76, 0xF9, 0x04, 0xEA, 0x2D, 0x68, 0xC4, 0x0F, 0x05, 0xFA, 0xAD, 0x69, 0x4C, 0x80, 0x12, 0x6C, 0xD0, 0x3D, 0xAA, 0x22, 0xFF, 0x89, 0x78, 0x57, 0xE8, 0x53, 0x25, 0x15, 0xD0, 0x7E, 0xD8, 0x55, 0x46, 0xA2, 0x04, 0xC7, 0x6E, 0xC1, 0xF3, 0x89, 0x7C, 0x2C, 0x0E, 0x93, 0x97, 0x91, 0x72, 0xF4, 0xF6, 0x90, 0x69, 0x0F, 0xB8, 0xC9, 0x17, 0xCF, 0x83, 0xAC, 0xA5, 0x1F, 0x69, 0x74, 0x12, 0x29, 0x2B, 0x21, 0x58, 0xF2, 0xDA, 0xE3, 0x25, 0x16, 0x09, 0x74, 0x40, 0x90, 0xAB, 0x1B, 0xE4, 0x06, 0x28, 0x77, 0xED, 0xC6, 0x16, 0x86, 0x0A, 0x27, 0xDD, 0x03, 0x01, 0x4D, 0x9A, 0x26, 0x6E, 0xC8, 0x9F, 0xD3, 0x9A, 0x4B, 0x59, 0xD1, 0x10, 0x9B, 0xEB, 0xA9, 0x58, 0x72, 0xBD, 0xA1, 0xFE, 0x9D, 0x86, 0xED, 0x29, 0xE9, 0x29, 0x49, 0x62, 0x4B, 0xD8, 0x7D, 0x2A, 0x7A, 0x66, 0x1B, 0xE5, 0x04, 0x81, 0x56, 0x10, 0x50, 0xAF, 0xB8, 0x48, 0x27, 0xC1, 0xC9, 0x46, 0xBD, 0x3F, 0x16, 0x06, 0xA5, 0x3D, 0x04, 0x9F, 0x0D, 0x54, 0x71, 0x1C, 0xF4, 0x82, 0xC0, 0x66, 0x74, 0xEA, 0x9C, 0x83, 0x3C, 0x27, 0x01, 0xDF, 0x6F, 0x56, 0xA8, 0x1B, 0xE3, 0x68, 0x55, 0x9F, 0xAB, 0x90, 0x67, 0x20, 0x25, 0xFA, 0x3D, 0x51, 0x2A, 0x23, 0x16, 0xCB, 0x06, 0x5A, 0xAD, 0xAC, 0xC8, 0x47, 0xF9, 0x39, 0x2E, 0x6A, 0xF8, 0xFA, 0x0A, 0xE8, 0x8A, 0x64, 0x84, 0x6B, 0xED, 0xDA, 0x8F, 0x2A, 0x08, 0x86, 0x8F, 0x56, 0x69, 0x64, 0xC3, 0x98, 0x55, 0x37, 0x9A, 0x48, 0x40, 0xDA, 0xD5, 0x03, 0x21
+};
+
+static const unsigned char App_AcexData[0x400] =
+{
+ 0xDF, 0x1C, 0x8B, 0x98, 0xE4, 0x6F, 0xA2, 0x35, 0x6C, 0xC3, 0x18, 0x17, 0x98, 0xF3, 0xCE, 0x54, 0x7E, 0x14, 0x2E, 0x7F, 0x1E, 0xD8, 0x6D, 0xCF, 0xBC, 0x29, 0x4E, 0xFE, 0x32, 0x2E, 0xC1, 0x11, 0xAD, 0x46, 0x9A, 0xC6, 0x70, 0xEA, 0xEE, 0x28, 0x55, 0x22, 0xE1, 0x36, 0x05, 0x1C, 0x04, 0x8A, 0xCE, 0x0F, 0x0C, 0x83, 0x8F, 0xC8, 0xD6, 0xDE, 0x11, 0x8E, 0xEA, 0xCF, 0xAD, 0x9B, 0xCF, 0x81, 0x0D, 0xEB, 0x71, 0x13, 0xB3, 0xD3, 0xAE, 0x83, 0x02, 0x4C, 0x0E, 0x10, 0x50, 0x59, 0x3C, 0xEE, 0x60, 0x06, 0xFB, 0x8C, 0x7F, 0xC2, 0x20, 0x24, 0x01, 0x62, 0x55, 0x87, 0x60, 0x0F, 0xAD, 0xFA, 0x73, 0x2E, 0xF6, 0x65, 0x62, 0xD2, 0xE5, 0x10, 0x45, 0x69, 0x70, 0x39, 0x03, 0xD1, 0x39, 0xEC, 0x50, 0xC1, 0xD4, 0x25, 0x39, 0xB2, 0x90, 0x11, 0x4E, 0x95, 0xCB, 0x19, 0xEB, 0xCA, 0x0F, 0xB5, 0xFA, 0xC7, 0xB0, 0xE2, 0xD7, 0xE0, 0x71, 0xC3, 0xE5, 0x55, 0x33, 0x9E, 0x5C, 0xDC, 0x4D, 0x3B, 0x51, 0x11, 0x0D, 0x31, 0x78, 0x96, 0xCA, 0xD7, 0x18, 0x58, 0xEE, 0x00, 0xE9, 0x28, 0xF2, 0x68, 0x76, 0xD4, 0x57, 0xFE, 0x65, 0xB1, 0x4B, 0x49, 0x3F, 0xF6, 0xA6, 0x58, 0x4A, 0xC7, 0xFC, 0xC4, 0xBB, 0x61, 0xBC, 0x58, 0x8D, 0x55, 0x65, 0xE6, 0x0A, 0x79, 0x39, 0x41, 0xB8, 0x80, 0x61, 0xF7, 0x05, 0xC3, 0xFE, 0xD6, 0x8B, 0x09, 0x82, 0xC2, 0x5F, 0xA6, 0x56, 0xF9, 0xEE, 0x1D, 0x0E, 0x06, 0x3E, 0x9F, 0x3F, 0xF1, 0x93, 0x9A, 0x4F, 0xA2, 0xD5, 0x91, 0x87, 0x8A, 0xFE, 0xCF, 0xC3, 0xFC, 0x8A, 0xB1, 0xC4, 0x78, 0xE9, 0xD1, 0x1A, 0xF7, 0xB1, 0xD3, 0x20, 0xCB, 0x83, 0xBE, 0x03, 0xD5, 0xCA, 0xA5, 0x5E, 0x17, 0xA6, 0x91, 0x10, 0xD4, 0xBE, 0x23, 0xD6, 0x4B, 0x4F, 0x03, 0xA9, 0xAE, 0xCF, 0xEC, 0xB2, 0x48, 0x03, 0x6D, 0xB8, 0x09, 0xE3, 0x5C, 0x6C, 0x62, 0x2C, 0xA9, 0x49, 0xE1, 0xF4, 0xF4, 0x0C, 0x6C, 0xC3, 0xE5, 0x2F, 0x9D, 0x50, 0xA0, 0x2B, 0x5A, 0x00, 0xC6, 0x72, 0x00, 0x0B, 0xA3, 0x04, 0x5D, 0x94, 0x46, 0xE7, 0x00, 0x1B, 0x48, 0x85, 0xB5, 0x61, 0x2C, 0xC9, 0x74, 0xCA, 0x2B, 0x43, 0x13, 0xC1, 0x78, 0x97, 0x5C, 0x33, 0x2F, 0x07, 0xC7, 0x85, 0xF0, 0xDA, 0xDB, 0x60, 0x96, 0x50, 0x0F, 0x7C, 0x4B, 0x7A, 0xD7, 0x17, 0x9D, 0xE4, 0xE5, 0xC3, 0xAB, 0x6F, 0x5D, 0xA5, 0x78, 0x32, 0xAD, 0x04, 0xDD, 0x96, 0x6E, 0xDC, 0x75, 0xFF, 0xC2, 0x2F, 0xFA, 0xA2, 0xEE, 0x46, 0x89, 0xCD, 0xAE, 0x69, 0x92, 0xA4, 0x48, 0xBC, 0x46, 0x47, 0xC4, 0x8C, 0x89, 0x63, 0xE1, 0x0A, 0x4D, 0x1C, 0xDC, 0x46, 0x2F, 0x5B, 0x70, 0x8A, 0x7C, 0xE9, 0x22, 0x9C, 0x09, 0x0B, 0xA8, 0x97, 0x40, 0xCA, 0x2A, 0x7D, 0x84, 0xA1, 0x04, 0x4A, 0x2E, 0xDB, 0xD7, 0xD0, 0x64, 0x43, 0x9C, 0xD0, 0x78, 0x11, 0x41, 0x88, 0x33, 0xDD, 0x31, 0x62, 0x90, 0x2D, 0x17, 0xF2, 0xC6, 0xA9, 0x2B, 0x9C, 0x70, 0xAB, 0xDC, 0xD3, 0xAB, 0x5D, 0xDA, 0xEE, 0x3D, 0x6C, 0x0E, 0x81, 0xFF, 0xF6, 0x67, 0x5A, 0x44, 0xF9, 0xAC, 0x07, 0x3D, 0x23, 0x94, 0x75, 0x65, 0x93, 0x20, 0x0C, 0xC5, 0x76, 0x1D, 0x0F, 0x65, 0x06, 0x3D, 0x21, 0xA2, 0xF0, 0x96, 0x80, 0xB7, 0x0A, 0x49, 0x53, 0x38, 0xA3, 0x5D, 0xC0, 0x74, 0x3C, 0xA4, 0xD9, 0x40, 0x36, 0x85, 0x1F, 0x8C, 0xD1, 0x2D, 0x15, 0xF9, 0xEF, 0x24, 0xA9, 0x7E, 0x9D, 0xB2, 0x1E, 0xF8, 0xA0, 0x72, 0x81, 0x17, 0x77, 0x73, 0xB1, 0x56, 0x7F, 0xAD, 0x05, 0xA2, 0xD2, 0x30, 0x5A, 0xF5, 0xD3, 0xAF, 0x0F, 0x10, 0x4A, 0x52, 0xD8, 0x09, 0x47, 0x97, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x21, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02
+};
+
+// DEMO
+static const unsigned char Demo_HdrPubK[0x100] =
+{
+ 0xB5, 0x11, 0x8D, 0x9E, 0x2D, 0xDB, 0x70, 0x6D, 0x6E, 0xEE, 0xAA, 0x21, 0xE0, 0x4E, 0x80, 0x0A, 0x96, 0x4A, 0x10, 0xD0, 0x9C, 0xD7, 0xD9, 0xD4, 0x94, 0x87, 0x72, 0xA2, 0xAF, 0x02, 0xA0, 0x05, 0x2E, 0xBF, 0x17, 0xEB, 0xFE, 0x5B, 0x9F, 0xB7, 0x0B, 0x1E, 0x3E, 0xF9, 0xAC, 0xBC, 0x7B, 0xB1, 0x56, 0x10, 0x24, 0x5F, 0x57, 0x2C, 0x08, 0xD0, 0x14, 0x79, 0x83, 0x84, 0x6A, 0x45, 0x25, 0xEB, 0xD9, 0xBE, 0x02, 0x21, 0xF7, 0x35, 0xC2, 0x74, 0x57, 0xC5, 0xAC, 0x34, 0x05, 0xC6, 0x9E, 0x82, 0xB8, 0xED, 0x78, 0xC4, 0x3B, 0xFD, 0x23, 0x59, 0x54, 0xD2, 0x0A, 0x0B, 0x5B, 0x25, 0xC0, 0x71, 0xC3, 0x84, 0x3A, 0xA7, 0xF9, 0x99, 0x86, 0xD8, 0xFE, 0x60, 0x10, 0x85, 0x77, 0x57, 0x76, 0x0C, 0x25, 0xE1, 0x18, 0x18, 0x3B, 0x83, 0xFD, 0x36, 0x7C, 0x84, 0x58, 0xC2, 0xC4, 0x68, 0x4F, 0xD1, 0xD7, 0x0A, 0x88, 0xFD, 0xCA, 0x97, 0xA1, 0xE5, 0xCE, 0x72, 0x63, 0xCF, 0x74, 0xD0, 0x20, 0xD9, 0xDE, 0x3F, 0xBB, 0x11, 0xF9, 0x21, 0xAB, 0x3F, 0x54, 0x41, 0xA7, 0xAA, 0xCA, 0xFC, 0xE1, 0x1A, 0x8C, 0x12, 0xC9, 0x39, 0x13, 0x5A, 0x81, 0x29, 0x49, 0xE8, 0xFB, 0x48, 0xC9, 0x4D, 0x50, 0x87, 0xAE, 0x51, 0xFB, 0x94, 0xFC, 0xF0, 0x9C, 0x70, 0x1C, 0xE8, 0x6E, 0x44, 0x53, 0x1E, 0x2F, 0x27, 0x5C, 0xB8, 0xEC, 0xBE, 0xFC, 0xD9, 0x98, 0x6A, 0x08, 0xD0, 0x5C, 0x4D, 0x78, 0x2D, 0x4D, 0x07, 0xAD, 0x5E, 0xB8, 0x51, 0x40, 0xE2, 0x2A, 0x7F, 0xB1, 0x54, 0x47, 0x5C, 0x99, 0x12, 0xC2, 0x6D, 0x5E, 0xED, 0x25, 0x30, 0x6A, 0x99, 0xC5, 0x0D, 0x65, 0x83, 0x68, 0x3A, 0xFD, 0x82, 0x59, 0x0D, 0xCE, 0x0B, 0x49, 0xBE, 0x17, 0x46, 0x51, 0xA9, 0xB6, 0x54, 0xE1, 0x18, 0xBD, 0x49, 0xE6, 0x7F
+};
+
+static const unsigned char Demo_HdrPrivK[0x100] =
+{
+ 0x1D, 0x7B, 0x79, 0x32, 0xAB, 0x46, 0xD2, 0xBC, 0x8E, 0xD6, 0x7F, 0x8F, 0x3A, 0x85, 0xAD, 0xA5, 0x8B, 0xA9, 0x0D, 0xA9, 0xDA, 0x0F, 0xEF, 0x61, 0x04, 0xBA, 0x35, 0x39, 0x36, 0x03, 0xD8, 0x68, 0x5F, 0x9F, 0x2F, 0xD6, 0xF6, 0x38, 0x96, 0xFD, 0xE7, 0xEA, 0x89, 0xD8, 0x7F, 0x7E, 0xC5, 0x29, 0x2F, 0xD9, 0x3B, 0x02, 0xE7, 0x1F, 0xBD, 0x63, 0x9C, 0x21, 0xD8, 0xFF, 0x43, 0x8A, 0x74, 0xCD, 0x3D, 0x4C, 0x09, 0xEE, 0xDB, 0xE0, 0xBE, 0x03, 0xD1, 0x92, 0xD7, 0x22, 0x35, 0x5A, 0x8C, 0xCE, 0xBE, 0x2B, 0xB4, 0x81, 0x47, 0x3F, 0x45, 0x75, 0x33, 0x31, 0x6B, 0xFF, 0x43, 0x5D, 0x17, 0x43, 0xAE, 0xD1, 0x25, 0xF7, 0xD9, 0xD5, 0x5C, 0xB6, 0x92, 0x5C, 0xB3, 0xF3, 0xF7, 0x65, 0x9F, 0x4C, 0x05, 0x12, 0xEC, 0xA8, 0x6D, 0x70, 0x65, 0x57, 0x6C, 0xD8, 0xE3, 0xD6, 0xFA, 0xC1, 0xFD, 0x54, 0xE8, 0x34, 0x67, 0x4D, 0x0A, 0x14, 0x2F, 0xA3, 0xD4, 0x81, 0x8C, 0xC3, 0xD0, 0x8B, 0x09, 0x08, 0x90, 0x70, 0x68, 0xA0, 0x0E, 0xD1, 0x0B, 0xAA, 0x71, 0xEC, 0x9A, 0x1A, 0x83, 0xFF, 0xA1, 0x70, 0xEB, 0xAC, 0xF2, 0xE9, 0x80, 0xA1, 0xB8, 0x20, 0x31, 0x83, 0xF5, 0x37, 0x01, 0x72, 0x06, 0x50, 0x05, 0x3F, 0x14, 0xF9, 0x29, 0x48, 0x84, 0xA0, 0x0E, 0xF7, 0xB8, 0x1D, 0xA3, 0x36, 0x5A, 0x78, 0x6D, 0x83, 0x90, 0x27, 0xE3, 0x50, 0x49, 0x2F, 0x65, 0xE5, 0x61, 0xED, 0x65, 0xBE, 0xEA, 0x34, 0xA6, 0x6A, 0xEF, 0x49, 0xB4, 0xE0, 0xBC, 0xC2, 0xA5, 0xB8, 0xEB, 0xA9, 0x2F, 0xBA, 0x26, 0x76, 0xB2, 0x5A, 0x3A, 0x3B, 0xFD, 0xAD, 0xFB, 0xE4, 0x79, 0xE2, 0x85, 0x54, 0x5B, 0xAB, 0x1F, 0x0A, 0xE5, 0x8B, 0x77, 0x3A, 0x10, 0x98, 0x26, 0x74, 0xC8, 0xB0, 0x82, 0xB1, 0xF9, 0x8F, 0x68, 0x59
+};
+
+static const unsigned char Demo_AcexData[0x400] =
+{
+ 0xD3, 0x7D, 0x42, 0xBA, 0x6A, 0x1E, 0xD8, 0x07, 0x3C, 0x4A, 0xC4, 0xCD, 0x8C, 0x68, 0x3D, 0xCD, 0xCD, 0xBD, 0x9D, 0xCE, 0xB5, 0x2A, 0xF9, 0x63, 0x3D, 0xA9, 0x54, 0x0A, 0x2E, 0x4C, 0xE1, 0x60, 0x4B, 0xD0, 0xC9, 0xEB, 0xEF, 0x31, 0x65, 0x70, 0xB9, 0x0E, 0x06, 0x3B, 0x3D, 0x42, 0x4C, 0x6E, 0x8D, 0x2C, 0xD4, 0x71, 0x29, 0x76, 0xB7, 0xDD, 0x8C, 0xDA, 0xE7, 0xE3, 0x96, 0xA7, 0xAA, 0xF8, 0xCA, 0x05, 0xE8, 0xA7, 0x0A, 0xDD, 0x01, 0x49, 0xBD, 0xF1, 0xA5, 0xE8, 0x16, 0x22, 0xEE, 0x47, 0x1F, 0xEF, 0x28, 0x48, 0x87, 0xA9, 0x2D, 0xFC, 0x4E, 0xD5, 0xA5, 0x98, 0xB1, 0xFE, 0x1B, 0xEB, 0xA9, 0x06, 0x3C, 0x76, 0xD9, 0xAA, 0x0E, 0x9C, 0x60, 0xFC, 0xE9, 0x77, 0x9D, 0x7F, 0x67, 0xAC, 0xF5, 0xC7, 0x49, 0x12, 0xFD, 0x76, 0xAC, 0xD2, 0x54, 0xDB, 0x73, 0x41, 0x10, 0x1F, 0x04, 0x3F, 0xD0, 0x6F, 0xE0, 0x80, 0x24, 0xCC, 0xEE, 0xBF, 0x25, 0x9D, 0x0D, 0x5A, 0x2A, 0x1C, 0xC5, 0xD4, 0xE3, 0x5D, 0x3A, 0xC1, 0x86, 0xD3, 0xD4, 0x52, 0x1C, 0x4C, 0xBF, 0x31, 0xEB, 0x54, 0xCA, 0x4C, 0x06, 0x50, 0x52, 0x87, 0xD4, 0x9D, 0x4A, 0x4B, 0x22, 0xE1, 0x4A, 0xE9, 0x4D, 0x05, 0xA8, 0x57, 0xEC, 0xF8, 0x90, 0xF8, 0x58, 0xC3, 0x8B, 0x3A, 0x0F, 0x88, 0x36, 0xF4, 0xE5, 0x44, 0x10, 0x80, 0x68, 0x86, 0x1D, 0xAE, 0x90, 0x20, 0x03, 0x22, 0x2D, 0x44, 0xBF, 0xAB, 0x2B, 0xA1, 0x14, 0xAD, 0x6B, 0x40, 0x57, 0xDB, 0xBB, 0xDA, 0x09, 0x4C, 0x51, 0x26, 0x9B, 0xE3, 0xD9, 0xF9, 0xE1, 0xBC, 0xF1, 0xF1, 0xCD, 0x30, 0xB4, 0xF5, 0x39, 0xD0, 0xBC, 0xF7, 0x98, 0x05, 0xAF, 0xA8, 0x33, 0x4B, 0xC1, 0x16, 0x0F, 0xF2, 0xC2, 0x79, 0x96, 0xEC, 0xBE, 0xA9, 0xF5, 0x55, 0x7C, 0x82, 0x95, 0x73, 0xB5, 0x11, 0x8D, 0x9E, 0x2D, 0xDB, 0x70, 0x6D, 0x6E, 0xEE, 0xAA, 0x21, 0xE0, 0x4E, 0x80, 0x0A, 0x96, 0x4A, 0x10, 0xD0, 0x9C, 0xD7, 0xD9, 0xD4, 0x94, 0x87, 0x72, 0xA2, 0xAF, 0x02, 0xA0, 0x05, 0x2E, 0xBF, 0x17, 0xEB, 0xFE, 0x5B, 0x9F, 0xB7, 0x0B, 0x1E, 0x3E, 0xF9, 0xAC, 0xBC, 0x7B, 0xB1, 0x56, 0x10, 0x24, 0x5F, 0x57, 0x2C, 0x08, 0xD0, 0x14, 0x79, 0x83, 0x84, 0x6A, 0x45, 0x25, 0xEB, 0xD9, 0xBE, 0x02, 0x21, 0xF7, 0x35, 0xC2, 0x74, 0x57, 0xC5, 0xAC, 0x34, 0x05, 0xC6, 0x9E, 0x82, 0xB8, 0xED, 0x78, 0xC4, 0x3B, 0xFD, 0x23, 0x59, 0x54, 0xD2, 0x0A, 0x0B, 0x5B, 0x25, 0xC0, 0x71, 0xC3, 0x84, 0x3A, 0xA7, 0xF9, 0x99, 0x86, 0xD8, 0xFE, 0x60, 0x10, 0x85, 0x77, 0x57, 0x76, 0x0C, 0x25, 0xE1, 0x18, 0x18, 0x3B, 0x83, 0xFD, 0x36, 0x7C, 0x84, 0x58, 0xC2, 0xC4, 0x68, 0x4F, 0xD1, 0xD7, 0x0A, 0x88, 0xFD, 0xCA, 0x97, 0xA1, 0xE5, 0xCE, 0x72, 0x63, 0xCF, 0x74, 0xD0, 0x20, 0xD9, 0xDE, 0x3F, 0xBB, 0x11, 0xF9, 0x21, 0xAB, 0x3F, 0x54, 0x41, 0xA7, 0xAA, 0xCA, 0xFC, 0xE1, 0x1A, 0x8C, 0x12, 0xC9, 0x39, 0x13, 0x5A, 0x81, 0x29, 0x49, 0xE8, 0xFB, 0x48, 0xC9, 0x4D, 0x50, 0x87, 0xAE, 0x51, 0xFB, 0x94, 0xFC, 0xF0, 0x9C, 0x70, 0x1C, 0xE8, 0x6E, 0x44, 0x53, 0x1E, 0x2F, 0x27, 0x5C, 0xB8, 0xEC, 0xBE, 0xFC, 0xD9, 0x98, 0x6A, 0x08, 0xD0, 0x5C, 0x4D, 0x78, 0x2D, 0x4D, 0x07, 0xAD, 0x5E, 0xB8, 0x51, 0x40, 0xE2, 0x2A, 0x7F, 0xB1, 0x54, 0x47, 0x5C, 0x99, 0x12, 0xC2, 0x6D, 0x5E, 0xED, 0x25, 0x30, 0x6A, 0x99, 0xC5, 0x0D, 0x65, 0x83, 0x68, 0x3A, 0xFD, 0x82, 0x59, 0x0D, 0xCE, 0x0B, 0x49, 0xBE, 0x17, 0x46, 0x51, 0xA9, 0xB6, 0x54, 0xE1, 0x18, 0xBD, 0x49, 0xE6, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x21, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02
+};
+
+// DLP
+static const unsigned char Dlp_HdrPubK[0x100] =
+{
+ 0xB3, 0x16, 0x68, 0xF1, 0xED, 0x59, 0xC8, 0x7F, 0xC6, 0x50, 0x21, 0xFE, 0x36, 0x7C, 0x55, 0xE7, 0x07, 0xF9, 0x1D, 0x1B, 0xF5, 0xB1, 0x2A, 0x6B, 0x3A, 0xDE, 0x2D, 0x4C, 0x51, 0xCD, 0x4C, 0x9F, 0xEE, 0x1D, 0xE4, 0xE8, 0xF0, 0xFD, 0x09, 0x8E, 0x0F, 0x92, 0x5F, 0xDB, 0x9C, 0x5C, 0x15, 0x55, 0x1A, 0x4D, 0x04, 0x8C, 0xB0, 0xA4, 0x88, 0x97, 0xC4, 0xD5, 0x92, 0x04, 0x42, 0x33, 0x84, 0x81, 0x06, 0xD6, 0xF2, 0x17, 0xDE, 0x83, 0x17, 0x50, 0xD0, 0x47, 0x61, 0x14, 0x0D, 0xB7, 0xC7, 0xA0, 0xC1, 0x8B, 0x82, 0x47, 0x13, 0xEE, 0x76, 0xA2, 0xA3, 0x8D, 0xCE, 0x55, 0xC1, 0xF3, 0x7A, 0xEA, 0x91, 0xE1, 0xB9, 0x2F, 0x8F, 0x9B, 0xC3, 0x7B, 0x51, 0x2F, 0xE7, 0xAD, 0x93, 0x9C, 0xFD, 0xDF, 0x19, 0xC8, 0x6C, 0x24, 0xC2, 0xE2, 0x91, 0x97, 0x1F, 0xEB, 0x4B, 0xD4, 0x46, 0x6C, 0x06, 0x93, 0xAF, 0xF5, 0x5E, 0x8F, 0x77, 0x25, 0xC4, 0x28, 0xC0, 0x82, 0x4A, 0x78, 0xE9, 0x14, 0x08, 0xC3, 0xC3, 0x58, 0x24, 0x44, 0x2D, 0x2B, 0xA7, 0xEE, 0x28, 0xEF, 0x1B, 0x6D, 0xAA, 0x9C, 0xED, 0x7F, 0x35, 0xCE, 0x86, 0x5C, 0x6B, 0x8A, 0x23, 0xD3, 0x9D, 0x05, 0x8F, 0xD2, 0x41, 0x93, 0x1D, 0x1D, 0x7E, 0xB0, 0x46, 0x23, 0x63, 0x07, 0xEA, 0x5F, 0x26, 0xE3, 0x81, 0x27, 0xB3, 0x95, 0xB1, 0x93, 0x59, 0xD4, 0x1A, 0xB8, 0x73, 0xD0, 0x09, 0x95, 0x2B, 0xE8, 0x8B, 0xE2, 0x73, 0x5F, 0x34, 0xB9, 0x98, 0x82, 0xF0, 0x11, 0xC6, 0x8F, 0x12, 0x4D, 0x09, 0x57, 0x10, 0x97, 0x22, 0x0E, 0xC8, 0x7D, 0x40, 0xC1, 0x9D, 0x12, 0x1F, 0x71, 0xFE, 0x1E, 0x1A, 0x8C, 0x3F, 0x56, 0xAC, 0x43, 0xC3, 0x66, 0x0C, 0x81, 0xAE, 0xC1, 0x8F, 0x68, 0xFF, 0x87, 0x07, 0x3C, 0xCD, 0x0A, 0x23, 0xDE, 0xBA, 0x9B
+};
+
+static const unsigned char Dlp_HdrPrivK[0x100] =
+{
+ 0x77, 0xC2, 0x7A, 0xB7, 0x9E, 0x13, 0xB6, 0x62, 0xCC, 0x09, 0x76, 0x51, 0xFB, 0xB9, 0xB5, 0xF0, 0x63, 0x82, 0x91, 0x96, 0xCA, 0xFC, 0x88, 0xF3, 0x60, 0x50, 0x87, 0x56, 0x4C, 0x35, 0xD0, 0x11, 0xFB, 0x38, 0x7E, 0x85, 0xCF, 0xF2, 0x46, 0xDB, 0x7B, 0x4A, 0x55, 0x54, 0x15, 0x01, 0xF7, 0x3A, 0x0B, 0xF6, 0x89, 0x1E, 0x54, 0x5A, 0x13, 0x05, 0xFB, 0x19, 0x1F, 0x26, 0x3D, 0xE7, 0x19, 0xAA, 0xF7, 0x19, 0xF2, 0x97, 0x47, 0xB3, 0xBE, 0x79, 0xCA, 0x6E, 0x91, 0x5A, 0xC9, 0xB9, 0xA6, 0x83, 0xB8, 0x2A, 0x45, 0x1A, 0xA7, 0x17, 0x86, 0xBA, 0x48, 0x49, 0x62, 0x3C, 0x33, 0x11, 0x51, 0x97, 0x5F, 0xAA, 0xE5, 0x1E, 0x0B, 0x19, 0x0C, 0xE6, 0x80, 0x6A, 0x5A, 0xB1, 0xD6, 0xCE, 0xDB, 0x6E, 0xC0, 0x5D, 0x29, 0x04, 0x84, 0x56, 0xE3, 0x29, 0x7E, 0xAC, 0xE8, 0xEE, 0xB1, 0x91, 0x37, 0xEB, 0x98, 0x9C, 0xBD, 0x02, 0x6A, 0x78, 0x61, 0xB0, 0x79, 0x1A, 0x9F, 0x30, 0x86, 0xF6, 0x71, 0x5A, 0x5A, 0x12, 0xA1, 0x9E, 0xA1, 0x68, 0x03, 0xE5, 0x95, 0xA8, 0x38, 0x58, 0x87, 0x08, 0x57, 0x35, 0x32, 0x47, 0x3B, 0xFC, 0x02, 0x6F, 0xCE, 0x55, 0x61, 0xA3, 0x2A, 0x6B, 0x2F, 0xF8, 0xEE, 0x8D, 0xFA, 0x43, 0x33, 0x02, 0x63, 0x47, 0x02, 0x78, 0x5A, 0x7F, 0x64, 0x07, 0x92, 0xB7, 0x7C, 0x09, 0x7C, 0xFE, 0x2D, 0x1C, 0xFC, 0x77, 0x9F, 0x19, 0x20, 0xDD, 0x6D, 0x4C, 0xFE, 0x49, 0x09, 0x47, 0xCA, 0x9B, 0x1C, 0x8C, 0x1F, 0x37, 0xAC, 0x14, 0x85, 0x56, 0xC0, 0xFD, 0xD6, 0x01, 0xB3, 0x40, 0xA3, 0x1A, 0x32, 0x78, 0xA0, 0xDD, 0x21, 0x75, 0xBF, 0x24, 0xD2, 0x93, 0x85, 0xED, 0x22, 0xAD, 0x99, 0x91, 0x87, 0x4A, 0xEC, 0xC0, 0x6C, 0x71, 0x00, 0x76, 0x08, 0x23, 0xA2, 0xF3, 0xCF, 0x61
+};
+
+static const unsigned char Dlp_AcexData[0x400] =
+{
+ 0xAC, 0xE2, 0xA7, 0xC3, 0x00, 0xDE, 0xE8, 0xE9, 0xE0, 0x03, 0xB3, 0x54, 0x08, 0xA8, 0xF8, 0x3A, 0x2E, 0xD8, 0x10, 0x6B, 0xEC, 0xDC, 0x4E, 0xEE, 0x62, 0x10, 0x71, 0x49, 0xD4, 0x43, 0xB1, 0x0E, 0x6B, 0x8C, 0xD7, 0x54, 0xD5, 0x62, 0x28, 0x3F, 0xAA, 0xDE, 0xA9, 0x7D, 0xED, 0x37, 0x7C, 0xE7, 0x89, 0x0B, 0x02, 0xB2, 0x72, 0x4B, 0x17, 0xDB, 0xE2, 0xD3, 0x7C, 0x94, 0x12, 0x3F, 0x2E, 0xA1, 0x08, 0x99, 0xCC, 0x7F, 0x93, 0xE6, 0x38, 0xC9, 0x37, 0x84, 0xD7, 0x11, 0x9D, 0x02, 0x4D, 0x66, 0xB4, 0x70, 0x9F, 0xD8, 0xC6, 0xDD, 0xD5, 0x13, 0x52, 0xF0, 0xA6, 0x78, 0x8C, 0x8E, 0x15, 0xA0, 0xA1, 0xF3, 0xC4, 0xC3, 0x48, 0x45, 0xA5, 0xBE, 0xC9, 0x7A, 0x8B, 0xD3, 0x95, 0xA5, 0x4C, 0xF1, 0xB3, 0x0C, 0x6C, 0x76, 0xA7, 0x57, 0xA1, 0x77, 0xDF, 0x2F, 0xC8, 0x06, 0xA6, 0x0D, 0x1A, 0x09, 0xE4, 0x38, 0x64, 0x07, 0xBE, 0x6A, 0xD2, 0xA0, 0xC0, 0xEC, 0x09, 0x64, 0x9F, 0x0D, 0x93, 0x0C, 0x89, 0xA2, 0x71, 0xD6, 0xC6, 0xC2, 0x54, 0x79, 0x2A, 0xA4, 0x31, 0x28, 0x24, 0x1A, 0xF3, 0x56, 0x78, 0x63, 0x99, 0x97, 0xA5, 0xCE, 0x8F, 0x52, 0x7A, 0x79, 0x51, 0xEE, 0x4C, 0x8B, 0x00, 0x9D, 0x5C, 0x3E, 0xD5, 0xAA, 0x24, 0x9C, 0x94, 0xC6, 0xA3, 0x99, 0x1B, 0x2D, 0xD4, 0xFF, 0xB4, 0x25, 0x73, 0x13, 0x33, 0x9F, 0x03, 0x6F, 0x1E, 0x75, 0xC4, 0x70, 0xF4, 0x07, 0x4F, 0x18, 0xFE, 0xBD, 0x8F, 0x2C, 0x9B, 0x33, 0xD4, 0x30, 0xA7, 0x18, 0x4A, 0xF1, 0xA4, 0xDD, 0x78, 0x41, 0xA0, 0xB8, 0x02, 0x8D, 0x51, 0x96, 0xBE, 0xE7, 0x17, 0x94, 0x66, 0x65, 0x27, 0xF7, 0x69, 0x48, 0x7E, 0xA9, 0x08, 0x71, 0x20, 0x76, 0xB7, 0x8E, 0xD2, 0xBF, 0x5C, 0x7E, 0x5E, 0x06, 0x45, 0xAB, 0x7E, 0x2E, 0xB3, 0x16, 0x68, 0xF1, 0xED, 0x59, 0xC8, 0x7F, 0xC6, 0x50, 0x21, 0xFE, 0x36, 0x7C, 0x55, 0xE7, 0x07, 0xF9, 0x1D, 0x1B, 0xF5, 0xB1, 0x2A, 0x6B, 0x3A, 0xDE, 0x2D, 0x4C, 0x51, 0xCD, 0x4C, 0x9F, 0xEE, 0x1D, 0xE4, 0xE8, 0xF0, 0xFD, 0x09, 0x8E, 0x0F, 0x92, 0x5F, 0xDB, 0x9C, 0x5C, 0x15, 0x55, 0x1A, 0x4D, 0x04, 0x8C, 0xB0, 0xA4, 0x88, 0x97, 0xC4, 0xD5, 0x92, 0x04, 0x42, 0x33, 0x84, 0x81, 0x06, 0xD6, 0xF2, 0x17, 0xDE, 0x83, 0x17, 0x50, 0xD0, 0x47, 0x61, 0x14, 0x0D, 0xB7, 0xC7, 0xA0, 0xC1, 0x8B, 0x82, 0x47, 0x13, 0xEE, 0x76, 0xA2, 0xA3, 0x8D, 0xCE, 0x55, 0xC1, 0xF3, 0x7A, 0xEA, 0x91, 0xE1, 0xB9, 0x2F, 0x8F, 0x9B, 0xC3, 0x7B, 0x51, 0x2F, 0xE7, 0xAD, 0x93, 0x9C, 0xFD, 0xDF, 0x19, 0xC8, 0x6C, 0x24, 0xC2, 0xE2, 0x91, 0x97, 0x1F, 0xEB, 0x4B, 0xD4, 0x46, 0x6C, 0x06, 0x93, 0xAF, 0xF5, 0x5E, 0x8F, 0x77, 0x25, 0xC4, 0x28, 0xC0, 0x82, 0x4A, 0x78, 0xE9, 0x14, 0x08, 0xC3, 0xC3, 0x58, 0x24, 0x44, 0x2D, 0x2B, 0xA7, 0xEE, 0x28, 0xEF, 0x1B, 0x6D, 0xAA, 0x9C, 0xED, 0x7F, 0x35, 0xCE, 0x86, 0x5C, 0x6B, 0x8A, 0x23, 0xD3, 0x9D, 0x05, 0x8F, 0xD2, 0x41, 0x93, 0x1D, 0x1D, 0x7E, 0xB0, 0x46, 0x23, 0x63, 0x07, 0xEA, 0x5F, 0x26, 0xE3, 0x81, 0x27, 0xB3, 0x95, 0xB1, 0x93, 0x59, 0xD4, 0x1A, 0xB8, 0x73, 0xD0, 0x09, 0x95, 0x2B, 0xE8, 0x8B, 0xE2, 0x73, 0x5F, 0x34, 0xB9, 0x98, 0x82, 0xF0, 0x11, 0xC6, 0x8F, 0x12, 0x4D, 0x09, 0x57, 0x10, 0x97, 0x22, 0x0E, 0xC8, 0x7D, 0x40, 0xC1, 0x9D, 0x12, 0x1F, 0x71, 0xFE, 0x1E, 0x1A, 0x8C, 0x3F, 0x56, 0xAC, 0x43, 0xC3, 0x66, 0x0C, 0x81, 0xAE, 0xC1, 0x8F, 0x68, 0xFF, 0x87, 0x07, 0x3C, 0xCD, 0x0A, 0x23, 0xDE, 0xBA, 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x21, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02
+};
+
+#endif
\ No newline at end of file
diff --git a/blz.c b/blz.c
new file mode 100644
index 0000000..8fc2355
--- /dev/null
+++ b/blz.c
@@ -0,0 +1,336 @@
+/*----------------------------------------------------------------------------*/
+/*-- blz.c - Bottom LZ coding for Nintendo GBA/DS --*/
+/*-- Copyright (C) 2011 CUE --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+#include "lib.h"
+#include "blz.h"
+
+/*----------------------------------------------------------------------------*/
+#define CMD_DECODE 0x00 // decode
+#define CMD_ENCODE 0x01 // encode
+
+#define BLZ_SHIFT 1 // bits to shift
+#define BLZ_MASK 0x80 // bits to check:
+ // ((((1 << BLZ_SHIFT) - 1) << (8 - BLZ_SHIFT)
+
+#define BLZ_THRESHOLD 2 // max number of bytes to not encode
+#define BLZ_N 0x1002 // max offset ((1 << 12) + 2)
+#define BLZ_F 0x12 // max coded ((1 << 4) + BLZ_THRESHOLD)
+
+#define RAW_MINIM 0x00000000 // empty file, 0 bytes
+#define RAW_MAXIM 0x00FFFFFF // 3-bytes length, 16MB - 1
+
+#define BLZ_MINIM 0x00000004 // header only (empty RAW file)
+#define BLZ_MAXIM 0x01400000 // 0x0120000A, padded to 20MB:
+ // * length, RAW_MAXIM
+ // * flags, (RAW_MAXIM + 7) / 8
+ // * header, 11
+ // 0x00FFFFFF + 0x00200000 + 12 + padding
+
+/*----------------------------------------------------------------------------*/
+#define BREAK(text) { printf(text); return; }
+#define EXIT(text) { printf(text); exit(-1); }
+
+/*----------------------------------------------------------------------------*/
+u8 *Memory(int length, int size);
+
+u8 *BLZ_Code(u8 *raw_buffer, int raw_len, u32 *new_len, int best);
+void BLZ_Invert(u8 *buffer, int length);
+
+/*----------------------------------------------------------------------------*/
+u8 *Memory(int length, int size) {
+ u8 *fb;
+
+ fb = (u8 *) calloc(length * size, size);
+ if (fb == NULL) EXIT("\nMemory error\n");
+
+ return(fb);
+}
+
+/*----------------------------------------------------------------------------*/
+void BLZ_Decode(char *filename) {
+ // u8 *pak_buffer, *raw_buffer, *pak, *raw, *pak_end, *raw_end;
+ // u32 pak_len, raw_len, len, pos, inc_len, hdr_len, enc_len, dec_len;
+ // u8 flags, mask;
+
+ // printf("- decoding '%s'", filename);
+
+ // // pak_buffer = Load(filename, &pak_len, BLZ_MINIM, BLZ_MAXIM);
+
+ // inc_len = *(u32 *)(pak_buffer + pak_len - 4);
+ // if (!inc_len) {
+ // enc_len = 0;
+ // dec_len = pak_len - 4;
+ // pak_len = 0;
+ // raw_len = dec_len;
+ // } else {
+ // if (pak_len < 8) EXIT("File has a bad header\n");
+ // hdr_len = pak_buffer[pak_len - 5];
+ // if ((hdr_len < 0x08) || (hdr_len > 0x0B)) EXIT("Bad header length\n");
+ // if (pak_len <= hdr_len) EXIT("Bad length\n");
+ // enc_len = *(u32 *)(pak_buffer + pak_len - 8) & 0x00FFFFFF;
+ // dec_len = pak_len - enc_len;
+ // pak_len = enc_len - hdr_len;
+ // raw_len = dec_len + enc_len + inc_len;
+ // if (raw_len > RAW_MAXIM) EXIT("Bad decoded length\n");
+ // }
+
+ // raw_buffer = (u8 *) Memory(raw_len, sizeof(char));
+
+ // pak = pak_buffer;
+ // raw = raw_buffer;
+ // pak_end = pak_buffer + dec_len + pak_len;
+ // raw_end = raw_buffer + raw_len;
+
+ // for (len = 0; len < dec_len; len++) *(raw++) = *(pak++);
+
+ // BLZ_Invert(pak_buffer + dec_len, pak_len);
+
+ // mask = 0;
+
+ // while (raw < raw_end) {
+ // if (!(mask >>= BLZ_SHIFT)) {
+ // if (pak == pak_end) break;
+ // flags = *pak++;
+ // mask = BLZ_MASK;
+ // }
+
+ // if (!(flags & mask)) {
+ // if (pak == pak_end) break;
+ // *raw++ = *pak++;
+ // } else {
+ // if (pak + 1 >= pak_end) break;
+ // pos = *pak++ << 8;
+ // pos |= *pak++;
+ // len = (pos >> 12) + BLZ_THRESHOLD + 1;
+ // if (raw + len > raw_end) {
+ // printf(", WARNING: wrong decoded length!");
+ // len = raw_end - raw;
+ // }
+ // pos = (pos & 0xFFF) + 3;
+ // while (len--) *(raw++) = *(raw - pos);
+ // }
+ // }
+
+ // BLZ_Invert(raw_buffer + dec_len, raw_len - dec_len);
+
+ // raw_len = raw - raw_buffer;
+
+ // if (raw != raw_end) printf(", WARNING: unexpected end of encoded file!");
+
+ // // Save(filename, raw_buffer, raw_len);
+
+ // free(raw_buffer);
+ // free(pak_buffer);
+
+ // printf("\n");
+}
+
+u8 *Load(char *filename, u32 *length, int min, int max) {
+ FILE *fp;
+ int fs;
+ u8 *fb;
+
+ if ((fp = fopen(filename, "rb")) == NULL) EXIT("\nFile open error\n");
+ fseek(fp, 0, SEEK_END);
+ fs = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ if ((fs < min) || (fs > max)) EXIT("\nFile size error\n");
+ fb = Memory(fs + 3, sizeof(char));
+ if (fread(fb, 1, fs, fp) != fs) EXIT("\nFile read error\n");
+ if (fclose(fp) == EOF) EXIT("\nFile close error\n");
+
+ *length = fs;
+
+ return(fb);
+}
+
+/*----------------------------------------------------------------------------*/
+u8* BLZ_Encode(char *filename, u32* pak_len, int mode) {
+ u8 *raw_buffer, *pak_buffer, *new_buffer;
+ u32 raw_len, new_len;
+
+ raw_buffer = Load(filename, &raw_len, RAW_MINIM, RAW_MAXIM);
+
+ pak_buffer = NULL;
+ *pak_len = BLZ_MAXIM + 1;
+
+ new_buffer = BLZ_Code(raw_buffer, raw_len, &new_len, mode);
+ if (new_len < *pak_len) {
+ if (pak_buffer != NULL) free(pak_buffer);
+ pak_buffer = new_buffer;
+ *pak_len = new_len;
+ }
+
+ return pak_buffer;
+}
+
+/*----------------------------------------------------------------------------*/
+u8 *BLZ_Code(u8 *raw_buffer, int raw_len, u32 *new_len, int best) {
+ u8 *pak_buffer, *pak, *raw, *raw_end, *flg, *tmp;
+ u32 pak_len, inc_len, hdr_len, enc_len, len, pos, max;
+ u32 len_best, pos_best, len_next, pos_next, len_post, pos_post;
+ u32 pak_tmp, raw_tmp;
+ u8 mask;
+
+#define SEARCH(l,p) { \
+ l = BLZ_THRESHOLD; \
+ \
+ max = raw - raw_buffer >= BLZ_N ? BLZ_N : raw - raw_buffer; \
+ for (pos = 3; pos <= max; pos++) { \
+ for (len = 0; len < BLZ_F; len++) { \
+ if (raw + len == raw_end) break; \
+ if (len >= pos) break; \
+ if (*(raw + len) != *(raw + len - pos)) break; \
+ } \
+ \
+ if (len > l) { \
+ p = pos; \
+ if ((l = len) == BLZ_F) break; \
+ } \
+ } \
+}
+
+ pak_tmp = 0;
+ raw_tmp = raw_len;
+
+ pak_len = raw_len + ((raw_len + 7) / 8) + 11;
+ pak_buffer = (u8 *) Memory(pak_len, sizeof(char));
+
+ BLZ_Invert(raw_buffer, raw_len);
+
+ pak = pak_buffer;
+ raw = raw_buffer;
+ raw_end = raw_buffer + raw_len;
+
+ mask = 0;
+
+ while (raw < raw_end) {
+ if (!(mask >>= BLZ_SHIFT)) {
+ *(flg = pak++) = 0;
+ mask = BLZ_MASK;
+ }
+
+ SEARCH(len_best, pos_best);
+
+ // LZ-CUE optimization start
+ if (best) {
+ if (len_best > BLZ_THRESHOLD) {
+ if (raw + len_best < raw_end) {
+ raw += len_best;
+ SEARCH(len_next, pos_next);
+ raw -= len_best - 1;
+ SEARCH(len_post, pos_post);
+ raw--;
+
+ if (len_next <= BLZ_THRESHOLD) len_next = 1;
+ if (len_post <= BLZ_THRESHOLD) len_post = 1;
+
+ if (len_best + len_next <= 1 + len_post) len_best = 1;
+ }
+ }
+ }
+ // LZ-CUE optimization end
+
+ *flg <<= 1;
+ if (len_best > BLZ_THRESHOLD) {
+ raw += len_best;
+ *flg |= 1;
+ *pak++ = ((len_best - (BLZ_THRESHOLD+1)) << 4) | ((pos_best - 3) >> 8);
+ *pak++ = (pos_best - 3) & 0xFF;
+ } else {
+ *pak++ = *raw++;
+ }
+
+ if (pak - pak_buffer + raw_len - (raw - raw_buffer) < pak_tmp + raw_tmp) {
+ pak_tmp = pak - pak_buffer;
+ raw_tmp = raw_len - (raw - raw_buffer);
+ }
+ }
+
+ while (mask && (mask != 1)) {
+ mask >>= BLZ_SHIFT;
+ *flg <<= 1;
+ }
+
+ pak_len = pak - pak_buffer;
+
+ BLZ_Invert(raw_buffer, raw_len);
+ BLZ_Invert(pak_buffer, pak_len);
+
+ if (!pak_tmp || (raw_len + 4 < ((pak_tmp + raw_tmp + 3) & -4) + 8)) {
+ pak = pak_buffer;
+ raw = raw_buffer;
+ raw_end = raw_buffer + raw_len;
+
+ while (raw < raw_end) *pak++ = *raw++;
+
+ while ((pak - pak_buffer) & 3) *pak++ = 0;
+
+ *(u32 *)pak = 0; pak += 4;
+ } else {
+ tmp = (u8 *) Memory(raw_tmp + pak_tmp + 11, sizeof(char));
+
+ for (len = 0; len < raw_tmp; len++)
+ tmp[len] = raw_buffer[len];
+
+ for (len = 0; len < pak_tmp; len++)
+ tmp[raw_tmp + len] = pak_buffer[len + pak_len - pak_tmp];
+
+ pak = pak_buffer;
+ pak_buffer = tmp;
+
+ free(pak);
+
+ pak = pak_buffer + raw_tmp + pak_tmp;
+
+ enc_len = pak_tmp;
+ hdr_len = 8;
+ inc_len = raw_len - pak_tmp - raw_tmp;
+
+ while ((pak - pak_buffer) & 3) {
+ *pak++ = 0xFF;
+ hdr_len++;
+ }
+
+ *(u32 *)pak = enc_len + hdr_len; pak += 3;
+ *pak++ = hdr_len;
+ *(u32 *)pak = inc_len - hdr_len; pak += 4;
+ }
+
+ *new_len = pak - pak_buffer;
+
+ return(pak_buffer);
+}
+
+/*----------------------------------------------------------------------------*/
+void BLZ_Invert(u8 *buffer, int length) {
+ u8 *bottom, ch;
+
+ bottom = buffer + length - 1;
+
+ while (buffer < bottom) {
+ ch = *buffer;
+ *buffer++ = *bottom;
+ *bottom-- = ch;
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+/*-- EOF Copyright (C) 2011 CUE --*/
+/*----------------------------------------------------------------------------*/
diff --git a/blz.h b/blz.h
new file mode 100644
index 0000000..d91ab4e
--- /dev/null
+++ b/blz.h
@@ -0,0 +1,9 @@
+#ifndef _BLZ_H_
+#define _BLZ_H_
+
+#define BLZ_NORMAL 0 // normal mode
+#define BLZ_BEST 1 // best mode
+
+u8 *BLZ_Code(u8 *raw_buffer, int raw_len, u32 *new_len, int best);
+
+#endif
diff --git a/certs.c b/certs.c
new file mode 100644
index 0000000..5cec50a
--- /dev/null
+++ b/certs.c
@@ -0,0 +1,139 @@
+#include "lib.h"
+#include "certs.h"
+
+// Cert Sizes
+
+u32 GetCertSize(u8 *cert)
+{
+ u32 SigSize = 0;
+ u32 SigPadding = 0;
+ GetCertSigSectionSizes(&SigSize,&SigPadding,cert);
+ if(!SigSize || !SigPadding) return 0;
+
+ Cert_Struct *certcore = (Cert_Struct*)(cert+4+SigSize+SigPadding);
+
+ u32 PubKSectionSize = GetCertPubkSectionSize((pubk_types)u8_to_u32(certcore->KeyType,BE));
+
+ return (4+SigSize+SigPadding+sizeof(Cert_Struct)+PubKSectionSize);
+}
+
+void GetCertSigSectionSizes(u32 *SigSize, u32 *SigPadding, u8 *cert)
+{
+ sig_types sig = (sig_types)u8_to_u32(cert,BE);
+ switch(sig){
+ case RSA_4096_SHA1 :
+ *SigSize = 0x200;
+ *SigPadding = 0x3C;
+ break;
+ case RSA_2048_SHA1 :
+ *SigSize = 0x100;
+ *SigPadding = 0x3C;
+ break;
+ case ECC_SHA1 :
+ *SigSize = 0x3C;
+ *SigPadding = 0x40;
+ break;
+ case RSA_4096_SHA256 :
+ *SigSize = 0x200;
+ *SigPadding = 0x3C;
+ break;
+ case RSA_2048_SHA256 :
+ *SigSize = 0x100;
+ *SigPadding = 0x3C;
+ break;
+ case ECC_SHA256 :
+ *SigSize = 0x3C;
+ *SigPadding = 0x40;
+ break;
+ default :
+ *SigSize = 0;
+ *SigPadding = 0;
+ break;
+ }
+ return;
+}
+
+u32 GetCertPubkSectionSize(pubk_types type)
+{
+ switch(type){
+ case RSA_4096_PUBK : return sizeof(rsa_4096_pubk_struct);
+ case RSA_2048_PUBK : return sizeof(rsa_2048_pubk_struct);
+ case ECC_PUBK : return sizeof(ecc_pubk_struct);
+ default : return 0;
+ }
+}
+
+// Issuer/Name Functions
+u8 *GetCertIssuer(u8 *cert)
+{
+ u32 SigSize = 0;
+ u32 SigPadding = 0;
+ GetCertSigSectionSizes(&SigSize,&SigPadding,cert);
+ if(!SigSize || !SigPadding) return 0;
+
+ Cert_Struct *certcore = (Cert_Struct*)(cert+4+SigSize+SigPadding);
+ return certcore->Issuer;
+}
+u8 *GetCertName(u8 *cert)
+{
+ u32 SigSize = 0;
+ u32 SigPadding = 0;
+ GetCertSigSectionSizes(&SigSize,&SigPadding,cert);
+ if(!SigSize || !SigPadding) return 0;
+
+ Cert_Struct *certcore = (Cert_Struct*)(cert+4+SigSize+SigPadding);
+ return certcore->Name;
+}
+
+int GenCertChildIssuer(u8 *dest, u8 *cert)
+{
+ u8 *Issuer = GetCertIssuer(cert);
+ u8 *Name = GetCertName(cert);
+
+ u32 out_size = strlen((char*)Issuer) + strlen((char*)Name) + 1;
+ if(out_size > 0x40) return MEM_ERROR;
+
+ memcpy(dest,Issuer,strlen((char*)Issuer));
+ dest[strlen((char*)Issuer)] = '-';
+ memcpy((dest+strlen((char*)Issuer)+1),Name,strlen((char*)Name));
+ return 0;
+}
+
+// Pubk
+pubk_types GetCertPubkType(u8 *cert)
+{
+ u32 SigSize = 0;
+ u32 SigPadding = 0;
+ GetCertSigSectionSizes(&SigSize,&SigPadding,cert);
+ if(!SigSize || !SigPadding) return 0;
+
+ Cert_Struct *certcore = (Cert_Struct*)(cert+4+SigSize+SigPadding);
+
+ return (pubk_types)u8_to_u32(certcore->KeyType,BE);
+}
+u8 *GetCertPubk(u8 *cert)
+{
+ u32 SigSize = 0;
+ u32 SigPadding = 0;
+ GetCertSigSectionSizes(&SigSize,&SigPadding,cert);
+ if(!SigSize || !SigPadding) return 0;
+ return (cert+4+SigSize+SigPadding+sizeof(Cert_Struct));
+}
+
+bool VerifyCert(u8 *cert, u8 *pubk)
+{
+ u32 SigSize = 0;
+ u32 SigPadding = 0;
+ GetCertSigSectionSizes(&SigSize,&SigPadding,cert);
+ if(!SigSize || !SigPadding) return 0;
+
+
+ u8 *signature = (cert+4);
+ u8 *data = (cert+4+SigSize+SigPadding);
+ u32 datasize = sizeof(Cert_Struct) + GetCertPubkSectionSize(GetCertPubkType(cert));
+
+ int result = ctr_sig(data,datasize,signature,pubk,NULL,u8_to_u32(cert,BE),CTR_RSA_VERIFY);
+
+ if(result == 0) return true;
+ else return false;
+}
\ No newline at end of file
diff --git a/certs.h b/certs.h
new file mode 100644
index 0000000..3d8ef47
--- /dev/null
+++ b/certs.h
@@ -0,0 +1,47 @@
+#ifndef _CERTS_H_
+#define _CERTS_H_
+
+typedef struct
+{
+ u8 Issuer[0x40];
+ u8 KeyType[4];
+ u8 Name[0x40];
+ u8 Unknown[4];
+} Cert_Struct;
+
+typedef struct
+{
+ u8 Modulus[0x200];
+ u8 PubExponent[4];
+ u8 Padding[0x34];
+} rsa_4096_pubk_struct;
+
+typedef struct
+{
+ u8 Modulus[0x100];
+ u8 PubExponent[4];
+ u8 Padding[0x34];
+} rsa_2048_pubk_struct;
+
+typedef struct
+{
+ u8 PubK[0x3C];
+ u8 Padding[0x3C];
+} ecc_pubk_struct;
+
+#endif
+// Cert Sizes
+u32 GetCertSize(u8 *cert);
+void GetCertSigSectionSizes(u32 *SigSize, u32 *SigPadding, u8 *cert);
+u32 GetCertPubkSectionSize(pubk_types type);
+
+// Issuer/Name Functions
+u8 *GetCertIssuer(u8 *cert);
+u8 *GetCertName(u8 *cert);
+int GenCertChildIssuer(u8 *dest, u8 *cert);
+
+// Pubk
+pubk_types GetCertPubkType(u8 *cert);
+u8 *GetCertPubk(u8 *cert);
+
+bool VerifyCert(u8 *cert, u8 *pubk);
\ No newline at end of file
diff --git a/cia.c b/cia.c
new file mode 100644
index 0000000..07986ae
--- /dev/null
+++ b/cia.c
@@ -0,0 +1,613 @@
+#include "lib.h"
+#include "ncch.h"
+#include "exheader.h"
+#include "exefs.h"
+#include "certs.h"
+#include "cia.h"
+#include "tik.h"
+#include "tmd.h"
+#include "titleid.h"
+#include "srl.h"
+#include "ncsd.h"
+
+// Private Prototypes
+/* cia_settings tools */
+void init_CIASettings(cia_settings *set);
+void free_CIASettings(cia_settings *set);
+int get_CIASettings(cia_settings *ciaset, user_settings *usrset);
+
+int GetSettingsFromUsrset(cia_settings *ciaset, user_settings *usrset);
+int GetSettingsFromNcch0(cia_settings *ciaset, u32 ncch0_offset);
+int GetCIADataFromNcch(cia_settings *ciaset, NCCH_Header *NcchHdr, ExtendedHeader_Struct *ExHeader);
+int GetMetaRegion(cia_settings *ciaset, ExtendedHeader_Struct *ExHeader, u8 *ExeFs);
+int GetContentFilePtrs(cia_settings *ciaset, user_settings *usrset);
+int GetSettingsFromSrl(cia_settings *ciaset);
+int GetSettingsFromCci(cia_settings *ciaset);
+
+u16 SetupVersion(u16 Major, u16 Minor, u16 Micro);
+
+int BuildCIA_CertChain(cia_settings *ciaset);
+int BuildCIA_Header(cia_settings *ciaset);
+
+int WriteCurrentSectionstoFile(cia_settings *ciaset);
+int WriteContentsToFile(cia_settings *ciaset, user_settings *usrset);
+int WriteTMDToFile(cia_settings *ciaset);
+
+int CryptContent(u8 *EncBuffer,u8 *DecBuffer,u64 size,u8 *title_key, u16 index, u8 mode);
+
+
+int build_CIA(user_settings *usrset)
+{
+ int result = 0;
+
+ // Init Settings
+ cia_settings *ciaset = malloc(sizeof(cia_settings));
+ if(!ciaset) {fprintf(stderr,"[CIA ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ init_CIASettings(ciaset);
+
+ // Get Settings
+ result = get_CIASettings(ciaset,usrset);
+ if(result) goto finish;
+
+ // Create Output File
+ ciaset->out = fopen(usrset->outfile,"wb");
+ if(!ciaset->out){
+ fprintf(stderr,"[CIA ERROR] Failed to create '%s'\n",usrset->outfile);
+ result = FAILED_TO_CREATE_OUTFILE;
+ goto finish;
+ }
+
+ // Create CIA Sections
+ /* Certificate Chain */
+ result = BuildCIA_CertChain(ciaset);
+ if(result) goto finish;
+
+ /* Ticket */
+ result = BuildTicket(ciaset);
+ if(result) goto finish;
+
+ /* CIA Header */
+ result = BuildCIA_Header(ciaset);
+ if(result) goto finish;
+ /* Write To File Current Sections to File */
+ /* Explanation :
+ In order to conserve memory, only one Content is in memory at a time.
+ This however has the limitation of only being able to generate TMD after all content
+ has been processed (, encrypted) and written to file.
+ */
+ result = WriteCurrentSectionstoFile(ciaset);
+ if(result) goto finish;
+
+ result = WriteContentsToFile(ciaset, usrset);
+ if(result) goto finish;
+
+ result = BuildTMD(ciaset);
+ if(result) goto finish;
+
+ result = WriteTMDToFile(ciaset);
+
+finish:
+ if(result != FAILED_TO_CREATE_OUTFILE && ciaset->out) fclose(ciaset->out);
+ free_CIASettings(ciaset);
+ return result;
+}
+
+void init_CIASettings(cia_settings *set)
+{
+ memset(set,0,sizeof(cia_settings));
+}
+
+void free_CIASettings(cia_settings *set)
+{
+ if(set->content.ContentFilePtrs){
+ for(u32 i = 1; i < set->content.ContentCount; i++){
+ fclose(set->content.ContentFilePtrs[i]);
+ }
+ free(set->content.ContentFilePtrs);
+ }
+ free(set->CIA_Sections.CertChain.buffer);
+ free(set->CIA_Sections.Ticket.buffer);
+ free(set->CIA_Sections.TitleMetaData.buffer);
+ free(set->CIA_Sections.CXI_MetaData.buffer);
+
+ memset(set,0,sizeof(cia_settings));
+
+ free(set);
+}
+
+int get_CIASettings(cia_settings *ciaset, user_settings *usrset)
+{
+ int result = 0;
+
+ // Transfering data from usrset
+ result = GetSettingsFromUsrset(ciaset,usrset);
+
+ if(usrset->Content0IsNcch){
+ result = GetSettingsFromNcch0(ciaset,0);
+ if(result) return result;
+ result = GetContentFilePtrs(ciaset,usrset);
+ if(result) return result;
+ }
+
+ else if(usrset->Content0IsSrl){
+ result = GetSettingsFromSrl(ciaset);
+ if(result) return result;
+ }
+
+ else if(usrset->Content0IsCci){
+ result = GetSettingsFromCci(ciaset);
+ if(result) return result;
+ }
+
+
+ return 0;
+}
+
+int GetSettingsFromUsrset(cia_settings *ciaset, user_settings *usrset)
+{
+ // General Stuff
+ ciaset->keys = &usrset->keys;
+ ciaset->content.content0 = usrset->Content0.buffer;
+ ciaset->content.content0_FileLen = usrset->Content0.size;
+ u32_to_u8(ciaset->Title_type,TYPE_CTR,BE);
+ ciaset->content.EncryptContents = usrset->EncryptContents;
+ ciaset->cert.ca_crl_version = 0;
+ ciaset->cert.signer_crl_version = 0;
+
+ for(int i = 0; i < 3; i++){
+ ciaset->Version[i] = usrset->Version[i];
+ }
+
+ // Random Number generator
+ u8 hash[0x20];
+ ctr_sha(ciaset->content.content0,0x100,hash,CTR_SHA_256);
+
+ // Ticket Data
+ memcpy(ciaset->tik.TicketID,(hash+0x8),8);
+ if(usrset->RandomTitleKey){
+ memcpy(ciaset->tik.TitleKey,(hash+0x10),16);
+ }
+ else{
+ memcpy(ciaset->tik.TitleKey,usrset->keys.aes.NormalKey,16);
+ }
+
+ ciaset->tik.ticket_format_ver = 1;
+ ciaset->tik.UnknownDataType = tik_normal;
+
+ int result = GenCertChildIssuer(ciaset->tik.TicketIssuer,usrset->keys.certs.tik_cert);
+ if(result) return result;
+
+ // Tmd Stuff
+ if(usrset->ContentID[0] > 0xffffffff){
+ ciaset->content.ContentId[0] = u8_to_u32(hash,BE);
+ }
+ else ciaset->content.ContentId[0] = usrset->ContentID[0];
+ ciaset->tmd.tmd_format_ver = 1;
+ result = GenCertChildIssuer(ciaset->tmd.TMDIssuer,usrset->keys.certs.tmd_cert);
+ return 0;
+}
+
+int GetSettingsFromNcch0(cia_settings *ciaset, u32 ncch0_offset)
+{
+ /* Sanity Checks */
+ if(!ciaset->content.content0_FileLen)
+ return CIA_NO_NCCH0;
+
+ u8 *ncch0 = (u8*)(ciaset->content.content0+ncch0_offset);
+
+ if(!IsNCCH(NULL,ncch0)){
+ fprintf(stderr,"[CIA ERROR] Content0 is not NCCH\n");
+ return CIA_INVALID_NCCH0;
+ }
+
+ /* Get Ncch0 Header */
+ NCCH_Header *hdr = NULL;
+ hdr = GetNCCH_CommonHDR(hdr,NULL,ncch0);
+ if(IsCfa(hdr)){
+ ciaset->content.IsCfa = true;
+ }
+
+ ciaset->content.ContentOffset[0] = 0;
+ ciaset->content.ContentSize[0] = GetNCCH_MediaSize(hdr)*GetNCCH_MediaUnitSize(hdr);
+ ciaset->content.TotalContentSize = ciaset->content.ContentSize[0];
+
+ /* Get Ncch0 Import Context */
+ NCCH_STRUCT *ncch_ctx = malloc(sizeof(NCCH_STRUCT));
+ if(!ncch_ctx){ fprintf(stderr,"[CIA ERROR] MEM ERROR\n"); return MEM_ERROR; }
+ memset(ncch_ctx,0x0,sizeof(NCCH_STRUCT));
+ GetCXIStruct(ncch_ctx,hdr);
+
+ /* Verify Ncch0 (Sig&Hash Checks) */
+ int result = VerifyNCCH(ncch0,ciaset->keys,true);
+ if(result == UNABLE_TO_LOAD_NCCH_KEY){
+ ciaset->content.KeyNotFound = true;
+ if(!ciaset->content.IsCfa){
+ fprintf(stderr,"[CIA WARNING] CXI AES Key could not be loaded\n");
+ fprintf(stderr," Meta Region, SaveDataSize, Remaster Version cannot be obtained\n");
+ }
+ }
+ else if(result != 0){
+ fprintf(stderr,"[CIA ERROR] Content 0 Is Corrupt\n");
+ return CIA_INVALID_NCCH0;
+ }
+
+ /* Gen Settings From Ncch0 */
+ endian_memcpy(ciaset->TitleID,hdr->title_id,8,LE);
+
+
+ /* Getting ExeFs/ExHeader */
+ u8 *ExeFs = malloc(ncch_ctx->exefs_size);
+ if(!ExeFs){ fprintf(stderr,"[CIA ERROR] MEM ERROR\n"); return MEM_ERROR; }
+ ExtendedHeader_Struct *ExHeader = malloc(ncch_ctx->exheader_size);
+ if(!ExHeader){ fprintf(stderr,"[CIA ERROR] MEM ERROR\n"); free(ExeFs); return MEM_ERROR; }
+
+ GetNCCHSection(ExeFs, ncch_ctx->exefs_size, 0, ncch0, ncch_ctx, ciaset->keys, ncch_exefs);
+ GetNCCHSection((u8*)ExHeader, ncch_ctx->exheader_size, 0, ncch0, ncch_ctx, ciaset->keys, ncch_ExHeader);
+
+ result = GetCIADataFromNcch(ciaset,hdr,ExHeader); // Data For TMD
+ if(result) goto finish;
+ result = GetMetaRegion(ciaset,ExHeader,ExeFs); // Meta Region
+ /* Finish */
+finish:
+ free(ExeFs);
+ free(ExHeader);
+
+ /* Return */
+ free(ncch_ctx);
+ return result;
+}
+
+int GetCIADataFromNcch(cia_settings *ciaset, NCCH_Header *NcchHdr, ExtendedHeader_Struct *ExHeader)
+{
+ u16 Category = u8_to_u16((ciaset->TitleID+2),BE);
+ bool IsPatch = (Category == 0x000E);
+ if(IsPatch||ciaset->content.IsCfa||ciaset->content.KeyNotFound) u32_to_u8(ciaset->tmd.SaveDataSize,0,LE);
+ else u32_to_u8(ciaset->tmd.SaveDataSize,(u32)GetSaveDataSize_frm_exhdr(ExHeader),LE);
+
+
+ if(ciaset->content.IsCfa||ciaset->content.KeyNotFound){
+ if(ciaset->Version[0] == 0xffff){ // '-major' wasn't set
+ if(ciaset->content.IsCfa){ // Is a CFA and can be decrypted
+ fprintf(stderr,"[CIA ERROR] Invalid major version. Use '-major' option.\n");
+ return CIA_BAD_VERSION;
+ }
+ else // CXI which cannot be decrypted
+ ciaset->Version[0] = 0;
+ }
+ }
+ else{ // Is a CXI and can be decrypted
+ if(ciaset->Version[0] != 0xffff){ // '-major' was set
+ fprintf(stderr,"[CIA ERROR] Option '-major' cannot be applied for cxi.\n");
+ return CIA_BAD_VERSION;
+ }
+ // Setting remaster ver
+ ciaset->Version[0] = GetRemasterVersion_frm_exhdr(ExHeader);
+ }
+ SetupVersion(ciaset->Version[0],ciaset->Version[1],ciaset->Version[2]);
+
+ u16 version = SetupVersion(ciaset->Version[0],ciaset->Version[1],ciaset->Version[2]);
+ u16_to_u8(ciaset->tik.TicketVersion,version,BE);
+ u16_to_u8(ciaset->tmd.TitleVersion,version,BE);
+ return 0;
+}
+
+int GetMetaRegion(cia_settings *ciaset, ExtendedHeader_Struct *ExHeader, u8 *ExeFs)
+{
+ if(ciaset->content.IsCfa || ciaset->content.KeyNotFound) return 0;
+ ciaset->CIA_Sections.CXI_MetaData.size = sizeof(MetaData_Struct) + GetExeFsSectionSize("icon",ExeFs);
+ ciaset->CIA_Sections.CXI_MetaData.buffer = malloc(ciaset->CIA_Sections.CXI_MetaData.size);
+ if(!ciaset->CIA_Sections.CXI_MetaData.buffer){ fprintf(stderr,"[CIA ERROR] MEM ERROR\n"); return MEM_ERROR; }
+ MetaData_Struct *hdr = (MetaData_Struct*)ciaset->CIA_Sections.CXI_MetaData.buffer;
+ memset(hdr,0,sizeof(MetaData_Struct));
+ GetDependancyList_frm_exhdr(hdr->DependancyList,ExHeader);
+ GetCoreVersion_frm_exhdr(hdr->CoreVersion,ExHeader);
+ if(DoesExeFsSectionExist("icon",ExeFs)){
+ u8 *IconDestPos = (ciaset->CIA_Sections.CXI_MetaData.buffer + sizeof(MetaData_Struct));
+ memcpy(IconDestPos,GetExeFsSection("icon",ExeFs),GetExeFsSectionSize("icon",ExeFs));
+ }
+ return 0;
+}
+
+int GetContentFilePtrs(cia_settings *ciaset, user_settings *usrset)
+{
+ ciaset->content.ContentFilePtrs = malloc(sizeof(FILE*)*CIA_MAX_CONTENT);
+ if(!ciaset->content.ContentFilePtrs){ fprintf(stderr,"[CIA ERROR] MEM ERROR\n"); return MEM_ERROR; }
+ memset(ciaset->content.ContentFilePtrs,0,sizeof(FILE*)*CIA_MAX_CONTENT);
+ int j = 1;
+ NCCH_Header *hdr = malloc(sizeof(NCCH_Header));
+ for(int i = 1; i < CIA_MAX_CONTENT; i++){
+ if(usrset->ContentPath[i]){
+ ciaset->content.ContentFilePtrs[j] = fopen(usrset->ContentPath[i],"rb");
+ if(!ciaset->content.ContentFilePtrs[j]){ fprintf(stderr,"[CIA ERROR] Failed to open '%s'\n",usrset->ContentPath[i]); return FAILED_TO_OPEN_FILE; }
+ if(usrset->ContentID[i] == 0x100000000){
+ u8 hash[0x20];
+ ctr_sha(usrset->ContentPath[i],strlen(usrset->ContentPath[i]),hash,CTR_SHA_256);
+ ciaset->content.ContentId[j] = u8_to_u32(hash,BE);
+ }
+ else ciaset->content.ContentId[j] = (u32)usrset->ContentID[i];
+ ciaset->content.ContentIndex[j] = (u16)i;
+
+ // Get Data from ncch HDR
+ GetNCCH_CommonHDR(hdr,ciaset->content.ContentFilePtrs[j],NULL);
+
+ // Get TitleID
+ memcpy(ciaset->content.ContentTitleId[j],hdr->title_id,8);
+
+ // Get Size
+ ciaset->content.ContentSize[j] = GetNCCH_MediaSize(hdr)*GetNCCH_MediaUnitSize(hdr);
+ ciaset->content.ContentOffset[j] = ciaset->content.TotalContentSize;
+
+ ciaset->content.TotalContentSize += ciaset->content.ContentSize[j];
+
+
+ // Finish get next content
+ j++;
+ }
+ }
+ free(hdr);
+ ciaset->content.ContentCount = j;
+
+ // Check Conflicting IDs
+ for(int i = 0; i < ciaset->content.ContentCount; i++){
+ for(j = i+1; j < ciaset->content.ContentCount; j++){
+ if(ciaset->content.ContentId[j] == ciaset->content.ContentId[i]){
+ fprintf(stderr,"[CIA ERROR] CIA Content %d and %d, have conflicting IDs\n",ciaset->content.ContentIndex[j],ciaset->content.ContentIndex[i]);
+ return CIA_CONFILCTING_CONTENT_IDS;
+ }
+ }
+ }
+ return 0;
+}
+
+int GetSettingsFromSrl(cia_settings *ciaset)
+{
+ SRL_Header *hdr = (SRL_Header*)ciaset->content.content0;
+ if(!hdr || ciaset->content.content0_FileLen < sizeof(SRL_Header)) {
+ fprintf(stderr,"[CIA ERROR] Invalid TWL SRL File\n");
+ return FAILED_TO_IMPORT_FILE;
+ }
+
+ // Check if TWL SRL File
+ if(u8_to_u16(&hdr->title_id[6],LE) != 0x0003){
+ fprintf(stderr,"[CIA ERROR] Invalid TWL SRL File\n");
+ return FAILED_TO_IMPORT_FILE;
+ }
+
+ // Generate and store Converted TitleID
+ u64_to_u8(ciaset->TitleID,ConvertTwlIdToCtrId(u8_to_u64(hdr->title_id,LE)),BE);
+ //memdump(stdout,"SRL TID: ",ciaset->TitleID,8);
+
+ // Get TWL Flag
+ ciaset->tmd.twl_flag = ((hdr->reserved_flags[3] & 6) >> 1);
+
+ // Get Remaster Version
+ u16 version = SetupVersion(hdr->rom_version,ciaset->Version[1],0);
+ u16_to_u8(ciaset->tik.TicketVersion,version,BE);
+ u16_to_u8(ciaset->tmd.TitleVersion,version,BE);
+
+ // Get SaveDataSize (Public and Private)
+ memcpy(ciaset->tmd.SaveDataSize,hdr->pub_save_data_size,4);
+ memcpy(ciaset->tmd.PrivSaveDataSize,hdr->priv_save_data_size,4);
+
+ // Setting CIA Content Settings
+ ciaset->content.ContentCount = 1;
+ ciaset->content.ContentOffset[0] = 0;
+ ciaset->content.ContentSize[0] = ciaset->content.content0_FileLen;
+ ciaset->content.TotalContentSize = ciaset->content.content0_FileLen;
+
+ return 0;
+}
+
+
+
+int GetSettingsFromCci(cia_settings *ciaset)
+{
+ int result = 0;
+
+ if(!IsCci(ciaset->content.content0)){
+ fprintf(stderr,"[CIA ERROR] Invalid CCI file\n");
+ return FAILED_TO_IMPORT_FILE;
+ }
+
+ u32 ncch0_offset = GetPartitionOffset(ciaset->content.content0,0);
+ if(!ncch0_offset){
+ fprintf(stderr,"[CIA ERROR] Invalid CCI file (invalid ncch0 size)\n");
+ return FAILED_TO_IMPORT_FILE;
+ }
+
+ result = GetSettingsFromNcch0(ciaset, ncch0_offset);
+ if(result){
+ fprintf(stderr,"Import of Ncch 0 failed(%d)\n",result);
+ return result;
+ }
+ ciaset->content.ContentCount = 1;
+ ciaset->content.CCIContentOffsets[0] = ncch0_offset;
+ NCCH_Header *hdr = malloc(sizeof(NCCH_Header));
+ for(int i = 1; i < 8; i++){
+ if(GetPartitionSize(ciaset->content.content0,i)){
+ ciaset->content.CCIContentOffsets[ciaset->content.ContentCount] = GetPartitionOffset(ciaset->content.content0,i);
+
+ // Get Data from ncch HDR
+ GetNCCH_CommonHDR(hdr,NULL,GetPartition(ciaset->content.content0,i));
+
+ // Get Size
+ ciaset->content.ContentSize[ciaset->content.ContentCount] = GetPartitionSize(ciaset->content.content0,i);
+ ciaset->content.ContentOffset[ciaset->content.ContentCount] = ciaset->content.TotalContentSize;
+
+ ciaset->content.TotalContentSize += ciaset->content.ContentSize[ciaset->content.ContentCount];
+
+ // Get ID
+ u8 hash[0x20];
+ ctr_sha((u8*)hdr,0x200,hash,CTR_SHA_256);
+ ciaset->content.ContentId[ciaset->content.ContentCount] = u8_to_u32(hash,BE);
+
+ // Get Index
+ ciaset->content.ContentIndex[ciaset->content.ContentCount] = i;
+
+ // Increment Content Count
+ ciaset->content.ContentCount++;
+ }
+ }
+ free(hdr);
+
+ return 0;
+}
+
+u16 SetupVersion(u16 Major, u16 Minor, u16 Micro)
+{
+ return (((Major << 10) & 0xFC00) | ((Minor << 4) & 0x3F0) | (Micro & 0xf));
+}
+
+int BuildCIA_CertChain(cia_settings *ciaset)
+{
+ ciaset->CIA_Sections.CertChain.size = GetCertSize(ciaset->keys->certs.ca_cert) + GetCertSize(ciaset->keys->certs.tik_cert) + GetCertSize(ciaset->keys->certs.tmd_cert);
+ ciaset->CIA_Sections.CertChain.buffer = malloc(ciaset->CIA_Sections.CertChain.size);
+ if(!ciaset->CIA_Sections.CertChain.buffer) { fprintf(stderr,"[CIA ERROR] MEM ERROR\n"); return MEM_ERROR; }
+ memcpy(ciaset->CIA_Sections.CertChain.buffer,ciaset->keys->certs.ca_cert,GetCertSize(ciaset->keys->certs.ca_cert));
+ memcpy((ciaset->CIA_Sections.CertChain.buffer+GetCertSize(ciaset->keys->certs.ca_cert)),ciaset->keys->certs.tik_cert,GetCertSize(ciaset->keys->certs.tik_cert));
+ memcpy((ciaset->CIA_Sections.CertChain.buffer+GetCertSize(ciaset->keys->certs.ca_cert)+GetCertSize(ciaset->keys->certs.tik_cert)),ciaset->keys->certs.tmd_cert,GetCertSize(ciaset->keys->certs.tmd_cert));
+ return 0;
+}
+
+int BuildCIA_Header(cia_settings *ciaset)
+{
+ // Allocating memory for header
+ ciaset->CIA_Sections.Header.size = sizeof(CIA_Header);
+ ciaset->CIA_Sections.Header.buffer = malloc(ciaset->CIA_Sections.Header.size);
+ if(!ciaset->CIA_Sections.Header.buffer){ fprintf(stderr,"[CIA ERROR] MEM ERROR\n"); return MEM_ERROR; }
+
+ CIA_Header *hdr = (CIA_Header*)ciaset->CIA_Sections.Header.buffer;
+
+ // Clearing
+ memset(hdr,0,sizeof(CIA_Header));
+
+ // Predict TMD Size
+ ciaset->CIA_Sections.TitleMetaData.size = PredictTMDSize(ciaset->content.ContentCount);
+
+ // Setting Data
+ u32_to_u8(hdr->HdrSize,sizeof(CIA_Header),LE);
+ u16_to_u8(hdr->Type,0x0,LE);
+ u16_to_u8(hdr->Version,0x0,LE);
+ u32_to_u8(hdr->CertChainSize,ciaset->CIA_Sections.CertChain.size,LE);
+ u32_to_u8(hdr->TicketSize,ciaset->CIA_Sections.Ticket.size,LE);
+ u32_to_u8(hdr->TitleMetaDataSize,ciaset->CIA_Sections.TitleMetaData.size,LE);
+ u32_to_u8(hdr->CXI_MetaSize,ciaset->CIA_Sections.CXI_MetaData.size,LE);
+ u64_to_u8(hdr->ContentSize,ciaset->content.TotalContentSize,LE);
+
+ // Recording Offsets
+ ciaset->CIA_Sections.CertChainOffset = align_value(sizeof(CIA_Header),0x40);
+ ciaset->CIA_Sections.TicketOffset = align_value(ciaset->CIA_Sections.CertChainOffset+ciaset->CIA_Sections.CertChain.size,0x40);
+ ciaset->CIA_Sections.TitleMetaDataOffset = align_value(ciaset->CIA_Sections.TicketOffset+ciaset->CIA_Sections.Ticket.size,0x40);
+ ciaset->CIA_Sections.ContentOffset = align_value(ciaset->CIA_Sections.TitleMetaDataOffset+ciaset->CIA_Sections.TitleMetaData.size,0x40);
+ ciaset->CIA_Sections.CXI_MetaDataOffset = align_value(ciaset->CIA_Sections.ContentOffset+ciaset->content.TotalContentSize,0x40);
+
+ // SetCIAContentIndex, actually works for all index values now. CIA files generated can now hold, with
+ // validity, 65536 contents. Or at least have a content with index value of 65535.
+ for(int i = 0; i < ciaset->content.ContentCount; i++){
+ // This works by treating the 0x2000 byte index array as an array of 2048 u32 values
+
+ // Used for determining which u32 chunk to write the value to
+ u16 section = ciaset->content.ContentIndex[i]/32;
+
+ // Calculating the value added to the u32
+ u32 value = 0x80000000/(1<content.ContentIndex[i]);
+
+ // Retrieving current u32 block
+ u32 cur_content_index_section = u8_to_u32(hdr->ContentIndex+(sizeof(u32)*section),BE);
+
+ // Adding value to block
+ cur_content_index_section += value;
+
+ // Returning block
+ u32_to_u8(hdr->ContentIndex+(sizeof(u32)*section),cur_content_index_section,BE);
+ }
+ return 0;
+}
+
+int WriteCurrentSectionstoFile(cia_settings *ciaset)
+{
+ WriteBuffer(ciaset->CIA_Sections.Header.buffer,ciaset->CIA_Sections.Header.size,0,ciaset->out);
+ WriteBuffer(ciaset->CIA_Sections.CertChain.buffer,ciaset->CIA_Sections.CertChain.size,ciaset->CIA_Sections.CertChainOffset,ciaset->out);
+ WriteBuffer(ciaset->CIA_Sections.Ticket.buffer,ciaset->CIA_Sections.Ticket.size,ciaset->CIA_Sections.TicketOffset,ciaset->out);
+ WriteBuffer(ciaset->CIA_Sections.CXI_MetaData.buffer,ciaset->CIA_Sections.CXI_MetaData.size,ciaset->CIA_Sections.CXI_MetaDataOffset,ciaset->out);
+ return 0;
+}
+
+int WriteContentsToFile(cia_settings *ciaset, user_settings *usrset)
+{
+ u8 *Content0 = ciaset->content.content0;
+ if(usrset->Content0IsCci) Content0 = (u8*)(ciaset->content.content0+ciaset->content.CCIContentOffsets[0]);
+
+ ctr_sha(Content0,ciaset->content.ContentSize[0],ciaset->content.ContentHash[0],CTR_SHA_256);
+ if(ciaset->content.EncryptContents) {
+ ciaset->content.ContentType[0] |= Encrypted;
+ CryptContent(Content0,Content0,ciaset->content.ContentSize[0],ciaset->tik.TitleKey,ciaset->content.ContentIndex[0],ENC);
+ }
+ WriteBuffer(Content0,ciaset->content.ContentSize[0],ciaset->content.ContentOffset[0]+ciaset->CIA_Sections.ContentOffset,ciaset->out);
+
+ // Free Buffer if Not CCI
+ if(!usrset->Content0IsCci){
+ free(usrset->Content0.buffer);
+ usrset->Content0.buffer = NULL;
+ usrset->Content0.size = 0;
+ }
+
+ // Add additional contents, recreating them with their new TitleID
+ if(usrset->Content0IsNcch){
+ u8 TitleId[8];
+ endian_memcpy(TitleId,ciaset->TitleID,8,LE);
+ for(int i = 1; i < ciaset->content.ContentCount; i++){
+ u8 *ContentBuff = RetargetNCCH(ciaset->content.ContentFilePtrs[i],ciaset->content.ContentSize[i],ciaset->content.ContentTitleId[i],TitleId,ciaset->keys);
+ if(!ContentBuff){
+ fprintf(stderr,"[CIA ERROR] Could not import content %d to CIA\n",i);
+ return FAILED_TO_IMPORT_FILE;
+ }
+ ctr_sha(ContentBuff,ciaset->content.ContentSize[i],ciaset->content.ContentHash[i],CTR_SHA_256);
+ if(ciaset->content.EncryptContents) {
+ ciaset->content.ContentType[i] |= Encrypted;
+ CryptContent(ContentBuff,ContentBuff,ciaset->content.ContentSize[i],ciaset->tik.TitleKey,ciaset->content.ContentIndex[i],ENC);
+ }
+ WriteBuffer(ContentBuff,ciaset->content.ContentSize[i],ciaset->content.ContentOffset[i]+ciaset->CIA_Sections.ContentOffset,ciaset->out);
+ free(ContentBuff);
+ }
+ }
+ else if(usrset->Content0IsCci){
+ for(int i = 1; i < ciaset->content.ContentCount; i++){
+ u8 *ContentBuff = (u8*)(ciaset->content.content0+ciaset->content.CCIContentOffsets[i]);
+ ctr_sha(ContentBuff,ciaset->content.ContentSize[i],ciaset->content.ContentHash[i],CTR_SHA_256);
+ if(ciaset->content.EncryptContents) {
+ ciaset->content.ContentType[i] |= Encrypted;
+ CryptContent(ContentBuff,ContentBuff,ciaset->content.ContentSize[i],ciaset->tik.TitleKey,ciaset->content.ContentIndex[i],ENC);
+ }
+ WriteBuffer(ContentBuff,ciaset->content.ContentSize[i],ciaset->content.ContentOffset[i]+ciaset->CIA_Sections.ContentOffset,ciaset->out);
+ }
+ free(usrset->Content0.buffer);
+ usrset->Content0.buffer = NULL;
+ usrset->Content0.size = 0;
+ }
+
+
+ return 0;
+}
+
+int WriteTMDToFile(cia_settings *ciaset)
+{
+ WriteBuffer(ciaset->CIA_Sections.TitleMetaData.buffer,ciaset->CIA_Sections.TitleMetaData.size,ciaset->CIA_Sections.TitleMetaDataOffset,ciaset->out);
+ return 0;
+}
+
+int CryptContent(u8 *EncBuffer,u8 *DecBuffer,u64 size,u8 *title_key, u16 index, u8 mode)
+{
+ //generating IV
+ u8 iv[16];
+ memset(&iv,0x0,16);
+ iv[0] = (index >> 8) & 0xff;
+ iv[1] = index & 0xff;
+ //Crypting content
+ ctr_aes_context ctx;
+ memset(&ctx,0x0,sizeof(ctr_aes_context));
+ ctr_init_aes_cbc(&ctx,title_key,iv,mode);
+ if(mode == ENC) ctr_aes_cbc(&ctx,DecBuffer,EncBuffer,size,ENC);
+ else ctr_aes_cbc(&ctx,EncBuffer,DecBuffer,size,DEC);
+ return 0;
+}
\ No newline at end of file
diff --git a/cia.h b/cia.h
new file mode 100644
index 0000000..7c14b09
--- /dev/null
+++ b/cia.h
@@ -0,0 +1,109 @@
+// Enums
+typedef enum
+{
+ CIA_NO_NCCH0 = -1,
+ CIA_INVALID_NCCH0 = -2,
+ CIA_CONFILCTING_CONTENT_IDS = -3,
+ CIA_BAD_VERSION = -4,
+} cia_errors;
+
+// Structs
+typedef struct
+{
+ u8 HdrSize[4];
+ u8 Type[2];
+ u8 Version[2];
+ u8 CertChainSize[4];
+ u8 TicketSize[4];
+ u8 TitleMetaDataSize[4];
+ u8 CXI_MetaSize[4];
+ u8 ContentSize[8];
+ u8 ContentIndex[0x2000];
+} CIA_Header;
+
+typedef struct
+{
+ u8 DependancyList[0x30*0x8];
+ u8 Reserved0[0x180];
+ u8 CoreVersion[4];
+ u8 Reserved1[0xfc];
+} MetaData_Struct;
+
+typedef struct
+{
+ FILE *out;
+
+ u8 TitleID[8];
+ u8 Title_type[4];
+ u16 Version[3];
+
+ keys_struct *keys;
+
+ struct{
+ u8 ca_crl_version;
+ u8 signer_crl_version;
+ } cert;
+
+ struct{
+ u8 TicketIssuer[0x40];
+ u8 ticket_format_ver;
+ u8 TicketID[8];
+ u8 DeviceID[8];
+ u8 TicketVersion[3];
+ u8 TitleKey[16];
+ u8 UnknownDataType;
+ } tik;
+
+ struct{
+ u8 TMDIssuer[0x40];
+ u8 tmd_format_ver;
+ u8 TitleVersion[3];
+ u8 SaveDataSize[4];
+ u8 PrivSaveDataSize[4];
+ u8 twl_flag;
+ } tmd;
+
+ struct{
+ u8 *content0;
+ u64 content0_FileLen;
+ bool IsCfa;
+ bool KeyNotFound;
+ bool EncryptContents;
+
+ FILE **ContentFilePtrs;
+ u64 CCIContentOffsets[CCI_MAX_CONTENT];
+ u16 ContentCount;
+ u64 ContentSize[CIA_MAX_CONTENT];
+ u64 ContentOffset[CIA_MAX_CONTENT];
+ u16 ContentIndex[CIA_MAX_CONTENT];
+ u16 ContentType[CIA_MAX_CONTENT];
+ u32 ContentId[CIA_MAX_CONTENT];
+ u8 ContentHash[CIA_MAX_CONTENT][0x20];
+
+ u8 ContentTitleId[CIA_MAX_CONTENT][8];
+ u64 TotalContentSize;
+ } content;
+
+ struct{
+ COMPONENT_STRUCT Header;
+
+ u32 CertChainOffset;
+ COMPONENT_STRUCT CertChain;
+
+ u32 TicketOffset;
+ COMPONENT_STRUCT Ticket;
+
+ u32 TitleMetaDataOffset;
+ COMPONENT_STRUCT TitleMetaData;
+
+ u32 CXI_MetaDataOffset;
+ COMPONENT_STRUCT CXI_MetaData;
+
+ u64 ContentOffset;
+ } CIA_Sections;
+
+ // Finish CIA data req.
+} cia_settings;
+
+// Public Prototypes
+int build_CIA(user_settings *usrset);
\ No newline at end of file
diff --git a/crypto.c b/crypto.c
new file mode 100644
index 0000000..90dc016
--- /dev/null
+++ b/crypto.c
@@ -0,0 +1,423 @@
+#include "lib.h"
+#include "crypto.h"
+
+// API for polarssl adapted/copied from CTRTOOL by neimod
+void ctr_sha(void *data, u64 size, u8 *hash, int mode)
+{
+ switch(mode){
+ case(CTR_SHA_1): sha1((u8*)data, size, hash); break;
+ case(CTR_SHA_256): sha2((u8*)data, size, hash, 0); break;
+ }
+}
+
+void ctr_add_counter(ctr_aes_context* ctx, u32 carry)
+{
+ u32 counter[4];
+ u32 sum;
+ int i;
+
+ for(i=0; i<4; i++)
+ counter[i] = (ctx->ctr[i*4+0]<<24) | (ctx->ctr[i*4+1]<<16) | (ctx->ctr[i*4+2]<<8) | (ctx->ctr[i*4+3]<<0);
+
+ for(i=3; i>=0; i--)
+ {
+ sum = counter[i] + carry;
+
+ if (sum < counter[i])
+ carry = 1;
+ else
+ carry = 0;
+
+ counter[i] = sum;
+ }
+
+ for(i=0; i<4; i++)
+ {
+ ctx->ctr[i*4+0] = counter[i]>>24;
+ ctx->ctr[i*4+1] = counter[i]>>16;
+ ctx->ctr[i*4+2] = counter[i]>>8;
+ ctx->ctr[i*4+3] = counter[i]>>0;
+ }
+}
+
+void ctr_init_counter(ctr_aes_context* ctx, u8 key[16], u8 ctr[16])
+{
+ aes_setkey_enc(&ctx->aes, key, 128);
+ memcpy(ctx->ctr, ctr, 16);
+}
+
+void ctr_crypt_counter_block(ctr_aes_context* ctx, u8 input[16], u8 output[16])
+{
+ int i;
+ u8 stream[16];
+
+
+ aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->ctr, stream);
+
+
+ if (input)
+ {
+ for(i=0; i<16; i++)
+ {
+ output[i] = stream[i] ^ input[i];
+ }
+ }
+ else
+ {
+ for(i=0; i<16; i++)
+ output[i] = stream[i];
+ }
+
+ ctr_add_counter(ctx, 1);
+}
+
+void ctr_crypt_counter(ctr_aes_context* ctx, u8* input, u8* output, u32 size)
+{
+ u8 stream[16];
+ u32 i;
+
+ while(size >= 16)
+ {
+ ctr_crypt_counter_block(ctx, input, output);
+
+ if (input)
+ input += 16;
+ if (output)
+ output += 16;
+
+ size -= 16;
+ }
+
+ if (size)
+ {
+ memset(stream, 0, 16);
+ ctr_crypt_counter_block(ctx, stream, stream);
+
+ if (input)
+ {
+ for(i=0; iaes, key, 128); break;
+ case(DEC): aes_setkey_dec(&ctx->aes, key, 128); break;
+ }
+ memcpy(ctx->iv, iv, 16);
+}
+
+void ctr_aes_cbc(ctr_aes_context* ctx,u8* input,u8* output,u32 size,u8 mode)
+{
+ switch(mode){
+ case(ENC): aes_crypt_cbc(&ctx->aes, AES_ENCRYPT, size, ctx->iv, input, output); break;
+ case(DEC): aes_crypt_cbc(&ctx->aes, AES_DECRYPT, size, ctx->iv, input, output); break;
+ }
+}
+
+void ctr_rsa_free(ctr_rsa_context* ctx)
+{
+ rsa_free(&ctx->rsa);
+}
+
+int ctr_rsa_init(ctr_rsa_context* ctx, u8 *modulus, u8 *private_exp, u8 *exponent, u8 rsa_type, u8 mode)
+{
+ // Sanity Check
+ if(ctx == NULL || modulus == NULL ||(private_exp == NULL && mode == RSAKEY_PRIV) || (exponent == NULL && mode == RSAKEY_PUB))
+ return Fail;
+ rsa_init(&ctx->rsa, RSA_PKCS_V15, 0);
+ u16 n_size = 0;
+ u16 d_size = 0;
+ u16 e_size = 0;
+ switch(rsa_type){
+ case RSA_2048:
+ ctx->rsa.len = 0x100;
+ n_size = 0x100;
+ d_size = 0x100;
+ e_size = 3;
+ break;
+ case RSA_4096:
+ ctx->rsa.len = 0x200;
+ n_size = 0x200;
+ d_size = 0x200;
+ e_size = 3;
+ break;
+ default: return Fail;
+ }
+
+ switch(mode){
+ case(RSAKEY_PUB):
+ if (mpi_read_binary(&ctx->rsa.N, modulus, n_size))
+ goto clean;
+ if (mpi_read_binary(&ctx->rsa.E, exponent, e_size))
+ goto clean;
+ break;
+ case(RSAKEY_PRIV):
+ if (mpi_read_binary(&ctx->rsa.N, modulus, n_size))
+ goto clean;
+ if (mpi_read_binary(&ctx->rsa.D, private_exp, d_size))
+ goto clean;
+ break;
+ default: return Fail;
+ }
+
+ return Good;
+clean:
+ ctr_rsa_free(ctx);
+ return Fail;
+}
+
+int ctr_sig(void *data, u64 size, u8 *signature, u8 *modulus, u8 *private_exp, u32 type, u8 mode)
+{
+ int result = 0;
+ int hashtype, hashlen, sigtype;
+ if(data == NULL || signature == NULL || modulus == NULL ||(private_exp == NULL && mode == CTR_RSA_SIGN))
+ return Fail;
+
+ switch(type){
+ case RSA_4096_SHA1:
+ hashtype = CTR_SHA_1;
+ hashlen = 0x14;
+ sigtype = RSA_4096;
+ case RSA_4096_SHA256:
+ hashtype = CTR_SHA_256;
+ hashlen = 0x20;
+ sigtype = RSA_4096;
+ break;
+ case RSA_2048_SHA1:
+ hashtype = CTR_SHA_1;
+ hashlen = 0x14;
+ sigtype = RSA_2048;
+ case RSA_2048_SHA256:
+ hashtype = CTR_SHA_256;
+ hashlen = 0x20;
+ sigtype = RSA_2048;
+ break;
+ case ECC_SHA1:
+ hashtype = CTR_SHA_1;
+ hashlen = 0x14;
+ sigtype = ECC;
+ case ECC_SHA256:
+ hashtype = CTR_SHA_256;
+ hashlen = 0x20;
+ sigtype = ECC;
+ break;
+ default: return Fail;
+ }
+
+ u8 hash[hashlen];
+ memset(hash,0,hashlen);
+ ctr_sha(data,size,hash,hashtype);
+ //memdump(stdout,"Data: ",data,size);
+ //memdump(stdout,"HashFor Sig: ",hash,hashlen);
+
+ if(sigtype == RSA_2048 || sigtype == RSA_4096)
+ result = ctr_rsa(hash,signature,modulus,private_exp,type,mode);
+ else if(sigtype == ECC){
+ printf("[!] ECC is not yet implemented\n");
+ result = Fail;
+ }
+ return result;
+}
+
+int ctr_rsa(u8 *hash, u8 *signature, u8 *modulus, u8 *private_exp, u32 type, u8 mode)
+{
+ int result = 0;
+ // Sanity Check
+ if(hash == NULL || signature == NULL || modulus == NULL ||(private_exp == NULL && mode == CTR_RSA_SIGN))
+ return Fail;
+
+ // Getting details from sig type
+ int hashtype;
+ int hashlen;
+ int sigtype;
+ switch(type){
+ case RSA_4096_SHA1:
+ hashtype = SIG_RSA_SHA1;
+ hashlen = 0x14;
+ sigtype = RSA_4096;
+ break;
+ case RSA_4096_SHA256:
+ hashtype = SIG_RSA_SHA256;
+ hashlen = 0x14;
+ sigtype = RSA_4096;
+ break;
+ case RSA_2048_SHA1:
+ hashtype = SIG_RSA_SHA1;
+ hashlen = 0x20;
+ sigtype = RSA_2048;
+ break;
+ case RSA_2048_SHA256:
+ hashtype = SIG_RSA_SHA256;
+ hashlen = 0x20;
+ sigtype = RSA_2048;
+ break;
+ default: return Fail;
+ }
+
+ // Setting up
+ ctr_rsa_context ctx;
+ u8 exponent[3] = {0x01,0x00,0x01};
+ switch(mode){
+ case CTR_RSA_VERIFY:
+ result = ctr_rsa_init(&ctx,modulus,NULL,(u8*)exponent,sigtype,RSAKEY_PUB);
+ break;
+ case CTR_RSA_SIGN:
+ result = ctr_rsa_init(&ctx,modulus,private_exp,NULL,sigtype,RSAKEY_PRIV);
+ break;
+ }
+ if(result)return result;
+
+ switch(mode){
+ case CTR_RSA_VERIFY:
+ return rsa_pkcs1_verify(&ctx.rsa,RSA_PUBLIC,hashtype,hashlen,hash,signature);
+ case CTR_RSA_SIGN:
+ return ctr_rsa_rsassa_pkcs1_v15_sign(&ctx.rsa,RSA_PRIVATE,hashtype,hashlen,hash,signature);
+ }
+ return Fail;
+}
+
+
+/**
+* Hacked from rsa.c, polarssl doesn't like generating signatures when only D and N are present
+**/
+int ctr_rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ size_t nb_pad, olen, ret;
+ unsigned char *p = sig;
+
+ if( ctx->padding != RSA_PKCS_V15 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ olen = ctx->len;
+
+ switch( hash_id )
+ {
+ case SIG_RSA_RAW:
+ nb_pad = olen - 3 - hashlen;
+ break;
+
+ case SIG_RSA_MD2:
+ case SIG_RSA_MD4:
+ case SIG_RSA_MD5:
+ nb_pad = olen - 3 - 34;
+ break;
+
+ case SIG_RSA_SHA1:
+ nb_pad = olen - 3 - 35;
+ break;
+
+ case SIG_RSA_SHA224:
+ nb_pad = olen - 3 - 47;
+ break;
+
+ case SIG_RSA_SHA256:
+ nb_pad = olen - 3 - 51;
+ break;
+
+ case SIG_RSA_SHA384:
+ nb_pad = olen - 3 - 67;
+ break;
+
+ case SIG_RSA_SHA512:
+ nb_pad = olen - 3 - 83;
+ break;
+
+
+ default:
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ if( ( nb_pad < 8 ) || ( nb_pad > olen ) )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ *p++ = 0;
+ *p++ = RSA_SIGN;
+ memset( p, 0xFF, nb_pad );
+ p += nb_pad;
+ *p++ = 0;
+
+ switch( hash_id )
+ {
+ case SIG_RSA_RAW:
+ memcpy( p, hash, hashlen );
+ break;
+
+ case SIG_RSA_MD2:
+ memcpy( p, ASN1_HASH_MDX, 18 );
+ memcpy( p + 18, hash, 16 );
+ p[13] = 2; break;
+
+ case SIG_RSA_MD4:
+ memcpy( p, ASN1_HASH_MDX, 18 );
+ memcpy( p + 18, hash, 16 );
+ p[13] = 4; break;
+
+ case SIG_RSA_MD5:
+ memcpy( p, ASN1_HASH_MDX, 18 );
+ memcpy( p + 18, hash, 16 );
+ p[13] = 5; break;
+
+ case SIG_RSA_SHA1:
+ memcpy( p, ASN1_HASH_SHA1, 15 );
+ memcpy( p + 15, hash, 20 );
+ break;
+
+ case SIG_RSA_SHA224:
+ memcpy( p, ASN1_HASH_SHA2X, 19 );
+ memcpy( p + 19, hash, 28 );
+ p[1] += 28; p[14] = 4; p[18] += 28; break;
+
+ case SIG_RSA_SHA256:
+ memcpy( p, ASN1_HASH_SHA2X, 19 );
+ memcpy( p + 19, hash, 32 );
+ p[1] += 32; p[14] = 1; p[18] += 32; break;
+
+ case SIG_RSA_SHA384:
+ memcpy( p, ASN1_HASH_SHA2X, 19 );
+ memcpy( p + 19, hash, 48 );
+ p[1] += 48; p[14] = 2; p[18] += 48; break;
+
+ case SIG_RSA_SHA512:
+ memcpy( p, ASN1_HASH_SHA2X, 19 );
+ memcpy( p + 19, hash, 64 );
+ p[1] += 64; p[14] = 3; p[18] += 64; break;
+
+ default:
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ mpi T, T1, T2;
+
+ mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 );
+
+ MPI_CHK( mpi_read_binary( &T, sig, ctx->len ) );
+
+ if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+ {
+ mpi_free( &T );
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
+
+ MPI_CHK( mpi_write_binary( &T, sig, olen ) );
+
+cleanup:
+
+ mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 );
+
+ return( 0 );
+}
\ No newline at end of file
diff --git a/crypto.h b/crypto.h
new file mode 100644
index 0000000..1380d1b
--- /dev/null
+++ b/crypto.h
@@ -0,0 +1,101 @@
+#ifndef _CTR_CRYPTO_H_
+#define _CTR_CRYPTO_H_
+
+#include "polarssl/config.h"
+#include "polarssl/aes.h"
+#include "polarssl/rsa.h"
+#include "polarssl/sha1.h"
+#include "polarssl/sha2.h"
+
+typedef enum
+{
+ RSA_4096_SHA1 = 0x00010000,
+ RSA_2048_SHA1 = 0x00010001,
+ ECC_SHA1 = 0x00010002,
+ RSA_4096_SHA256 = 0x00010003,
+ RSA_2048_SHA256 = 0x00010004,
+ ECC_SHA256 = 0x00010005
+} sig_types;
+
+typedef enum
+{
+ RSA_2048 = 0,
+ RSA_4096 = 1,
+ ECC = 2,
+} ctr_sig_types;
+
+typedef enum
+{
+ CTR_RSA_VERIFY = 0,
+ CTR_RSA_SIGN = 1,
+} ctr_rsa_functions;
+
+typedef enum
+{
+ CTR_SHA_1 = 1,
+ CTR_SHA_256 = 256,
+} ctr_sha_modes;
+
+typedef enum
+{
+ RSA_4096_PUBK = 0,
+ RSA_2048_PUBK,
+ ECC_PUBK
+} pubk_types;
+
+typedef enum
+{
+ ENC,
+ DEC
+} aescbcmode;
+
+typedef enum
+{
+ RSAKEY_INVALID,
+ RSAKEY_PRIV,
+ RSAKEY_PUB
+} rsakeytype;
+
+typedef struct
+{
+ u8 ctr[16];
+ u8 iv[16];
+ aes_context aes;
+} ctr_aes_context;
+
+typedef struct
+{
+ rsa_context rsa;
+} ctr_rsa_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+// SHA
+void ctr_sha(void *data, u64 size, u8 *hash, int mode);
+// AES
+void ctr_add_counter(ctr_aes_context* ctx, u32 carry);
+void ctr_init_counter(ctr_aes_context* ctx, u8 key[16],u8 ctr[16]);
+void ctr_crypt_counter_block(ctr_aes_context* ctx, u8 input[16], u8 output[16]);
+void ctr_crypt_counter(ctr_aes_context* ctx, u8* input, u8* output, u32 size);
+void ctr_init_aes_cbc(ctr_aes_context* ctx,u8 key[16],u8 iv[16], u8 mode);
+void ctr_aes_cbc(ctr_aes_context* ctx,u8* input,u8* output,u32 size,u8 mode);
+// RSA
+void ctr_rsa_free(ctr_rsa_context* ctx);
+int ctr_rsa_init(ctr_rsa_context* ctx, u8 *modulus, u8 *private_exp, u8 *exponent, u8 rsa_type, u8 mode);
+int ctr_rsa(u8 *hash, u8 *signature, u8 *modulus, u8 *private_exp, u32 type, u8 mode);
+int ctr_rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+// Signature Functions
+int ctr_sig(void *data, u64 size, u8 *signature, u8 *modulus, u8 *private_exp, u32 type, u8 mode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/elf.c b/elf.c
new file mode 100644
index 0000000..18b701f
--- /dev/null
+++ b/elf.c
@@ -0,0 +1,954 @@
+#include "lib.h"
+#include "ncch.h"
+#include "elf_hdr.h"
+#include "elf.h"
+#include "blz.h"
+
+int ImportPlainRegionFromFile(ncch_settings *ncchset);
+int ImportExeFsCodeBinaryFromFile(ncch_settings *ncchset);
+
+u32 GetPageSize(ncch_settings *ncchset);
+u32 SizeToPage(u32 memorySize, ElfContext *elf);
+
+int GetBSS_SizeFromElf(ElfContext *elf, u8 *ElfFile, ncch_settings *ncchset);
+int ImportPlainRegionFromElf(ElfContext *elf, u8 *ElfFile, ncch_settings *ncchset);
+int CreateExeFsCode(ElfContext *elf, u8 *ElfFile, ncch_settings *ncchset);
+int CreateCodeSegmentFromElf(CodeSegment *out, ElfContext *elf, u8 *ElfFile, char **Names, u32 NameNum);
+ElfSegment** GetContinuousSegments(u16 *ContinuousSegmentNum, ElfContext *elf, char **Names, u32 NameNum);
+ElfSegment** GetSegments(u16 *SegmentNum, ElfContext *elf, char **Names, u32 NameNum);
+
+// ELF Functions
+int GetElfContext(ElfContext *elf, u8 *ElfFile);
+int GetElfSectionEntries(ElfContext *elf, u8 *ElfFile);
+int GetElfProgramEntries(ElfContext *elf, u8 *ElfFile);
+void PrintElfContext(ElfContext *elf, u8 *ElfFile);
+int ReadElfHdr(ElfContext *elf, u8 *ElfFile);
+
+int CreateElfSegments(ElfContext *elf, u8 *ElfFile);
+bool IsIgnoreSection(ElfSectionEntry info);
+
+/* ELF Section Entry Functions */
+u8* GetELFSectionHeader(u16 Index, ElfContext *elf, u8 *ElfFile);
+u8* GetELFSectionEntry(u16 Index, ElfContext *elf, u8 *ElfFile);
+char* GetELFSectionEntryName(u16 Index, ElfContext *elf, u8 *ElfFile);
+u64 GetELFSectionEntryType(u16 Index, ElfContext *elf, u8 *ElfFile);
+u64 GetELFSectionEntryFlags(u16 Index, ElfContext *elf, u8 *ElfFile);
+u64 GetELFSectionEntryAddress(u16 Index, ElfContext *elf, u8 *ElfFile);
+u64 GetELFSectionEntryFileOffset(u16 Index, ElfContext *elf, u8 *ElfFile);
+u64 GetELFSectionEntrySize(u16 Index, ElfContext *elf, u8 *ElfFile);
+u64 GetELFSectionEntryAlignment(u16 Index, ElfContext *elf, u8 *ElfFile);
+
+u16 GetElfSectionIndexFromName(char *Name, ElfContext *elf, u8 *ElfFile);
+
+bool IsBss(ElfSectionEntry *Section);
+bool IsData(ElfSectionEntry *Section);
+bool IsRO(ElfSectionEntry *Section);
+bool IsText(ElfSectionEntry *Section);
+
+/* ELF Program Entry Functions */
+u8* GetELFProgramHeader(u16 Index, ElfContext *elf, u8 *ElfFile);
+u8* GetELFProgramEntry(u16 Index, ElfContext *elf, u8 *ElfFile);
+u64 GetELFProgramEntryType(u16 Index, ElfContext *elf, u8 *ElfFile);
+u64 GetELFProgramEntryFlags(u16 Index, ElfContext *elf, u8 *ElfFile);
+u64 GetELFProgramEntryFileSize(u16 Index, ElfContext *elf, u8 *ElfFile);
+u64 GetELFProgramEntryFileOffset(u16 Index, ElfContext *elf, u8 *ElfFile);
+u64 GetELFProgramEntryMemorySize(u16 Index, ElfContext *elf, u8 *ElfFile);
+u64 GetELFProgramEntryVAddress(u16 Index, ElfContext *elf, u8 *ElfFile);
+u64 GetELFProgramEntryPAddress(u16 Index, ElfContext *elf, u8 *ElfFile);
+u64 GetELFProgramEntryAlignment(u16 Index, ElfContext *elf, u8 *ElfFile);
+
+
+int BuildExeFsCode(ncch_settings *ncchset)
+{
+ int result = 0;
+ if(ncchset->ComponentFilePtrs.plainregion){ // Import PlainRegion from file
+ result = ImportPlainRegionFromFile(ncchset);
+ if(result) return result;
+ }
+ if(!ncchset->Options.IsBuildingCodeSection){ // Import ExeFs Code from file and return
+ result = ImportExeFsCodeBinaryFromFile(ncchset);
+ return result;
+ }
+
+ /* Import ELF */
+ u8 *ElfFile = malloc(ncchset->ComponentFilePtrs.elf_size);
+ if(!ElfFile) {fprintf(stderr,"[ELF ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ ReadFile_64(ElfFile,ncchset->ComponentFilePtrs.elf_size,0,ncchset->ComponentFilePtrs.elf);
+
+ /* Create ELF Context */
+ ElfContext *elf = malloc(sizeof(ElfContext));
+ if(!elf) {fprintf(stderr,"[ELF ERROR] MEM ERROR\n"); free(ElfFile); return MEM_ERROR;}
+ memset(elf,0,sizeof(ElfContext));
+
+ result = GetElfContext(elf,ElfFile);
+ if(result) goto finish;
+
+ /* Setting Page Size */
+ elf->PageSize = GetPageSize(ncchset);
+
+ if(!ncchset->ComponentFilePtrs.plainregion){
+ result = ImportPlainRegionFromElf(elf,ElfFile,ncchset);
+ if(result) goto finish;
+ }
+
+#ifdef ELF_DEBUG
+ PrintElfContext(elf,ElfFile);
+#endif
+
+ result = CreateExeFsCode(elf,ElfFile,ncchset);
+ if(result) goto finish;
+
+ result = GetBSS_SizeFromElf(elf,ElfFile,ncchset);
+ if(result) goto finish;
+
+finish:
+ if(result){
+ if(result == NOT_ELF_FILE) fprintf(stderr,"[ELF ERROR] Not ELF File\n");
+ else if(result == NOT_ARM_ELF) fprintf(stderr,"[ELF ERROR] Not ARM ELF\n");
+ else if(result == NON_EXECUTABLE_ELF) fprintf(stderr,"[ELF ERROR] Not Executeable ELF\n");
+ else if(result == NOT_FIND_BSS_SIZE) fprintf(stderr,"[ELF ERROR] BSS Size Could not be found\n");
+ else if(result == NOT_FIND_CODE_SECTIONS) fprintf(stderr,"[ELF ERROR] Failed to retrieve code sections from ELF\n");
+ else fprintf(stderr,"[ELF ERROR] Failed to process ELF file (%d)\n",result);
+ }
+ for(int i = 0; i < elf->ActiveSegments; i++){
+ free(elf->Segments[i].Header);
+ free(elf->Segments[i].Sections);
+ }
+ free(ElfFile);
+ free(elf->Sections);
+ free(elf->ProgramHeaders);
+ free(elf->Segments);
+ free(elf);
+ return result;
+}
+
+int ImportPlainRegionFromFile(ncch_settings *ncchset)
+{
+ ncchset->Sections.PlainRegion.size = align_value(ncchset->ComponentFilePtrs.plainregion_size,ncchset->Options.MediaSize);
+ ncchset->Sections.PlainRegion.buffer = malloc(ncchset->Sections.PlainRegion.size);
+ if(!ncchset->Sections.PlainRegion.buffer) {fprintf(stderr,"[ELF ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ ReadFile_64(ncchset->Sections.PlainRegion.buffer,ncchset->ComponentFilePtrs.plainregion_size,0,ncchset->ComponentFilePtrs.plainregion);
+ return 0;
+}
+
+int ImportExeFsCodeBinaryFromFile(ncch_settings *ncchset)
+{
+ u32 size = ncchset->ComponentFilePtrs.code_size;
+ u8 *buffer = malloc(size);
+ if(!buffer) {fprintf(stderr,"[ELF ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ ReadFile_64(buffer,size,0,ncchset->ComponentFilePtrs.code);
+
+ ncchset->ExeFs_Sections.Code.size = ncchset->ComponentFilePtrs.code_size;
+ ncchset->ExeFs_Sections.Code.buffer = malloc(ncchset->ExeFs_Sections.Code.size);
+ if(!ncchset->ExeFs_Sections.Code.buffer) {fprintf(stderr,"[ELF ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ ReadFile_64(ncchset->ExeFs_Sections.Code.buffer,ncchset->ExeFs_Sections.Code.size,0,ncchset->ComponentFilePtrs.code);
+ if(ncchset->Options.CompressCode){
+ u32 new_len;
+ ncchset->ExeFs_Sections.Code.buffer = BLZ_Code(buffer,size,&new_len,BLZ_NORMAL);
+ ncchset->ExeFs_Sections.Code.size = new_len;
+ free(buffer);
+ }
+ else{
+ ncchset->ExeFs_Sections.Code.size = size;
+ ncchset->ExeFs_Sections.Code.buffer = buffer;
+ }
+ return 0;
+}
+
+u32 GetPageSize(ncch_settings *ncchset)
+{
+ if(ncchset->yaml_set->DefaultSpec.Option.PageSize)
+ return strtoul(ncchset->yaml_set->DefaultSpec.Option.PageSize,NULL,10);
+ return 0x1000;
+}
+
+u32 SizeToPage(u32 memorySize, ElfContext *elf)
+{
+ return align_value(memorySize,elf->PageSize)/elf->PageSize;
+}
+
+
+int GetBSS_SizeFromElf(ElfContext *elf, u8 *ElfFile, ncch_settings *ncchset)
+{
+ for(int i = 0; i < elf->SectionTableEntryCount; i++){
+ if(IsBss(&elf->Sections[i])) {
+ ncchset->CodeDetails.BSS_Size = elf->Sections[i].Size;
+ return 0;
+ }
+ }
+ return NOT_FIND_BSS_SIZE;
+}
+
+int ImportPlainRegionFromElf(ElfContext *elf, u8 *ElfFile, ncch_settings *ncchset) // Doesn't work same as N makerom
+{
+ if(!ncchset->yaml_set->DefaultSpec.PlainRegionNum) return 0;
+ u16 *Index = malloc(sizeof(u16)*ncchset->yaml_set->DefaultSpec.PlainRegionNum);
+
+ /* Getting Index Values for each section */
+ for(int i = 0; i < ncchset->yaml_set->DefaultSpec.PlainRegionNum; i++){
+ Index[i] = GetElfSectionIndexFromName(ncchset->yaml_set->DefaultSpec.PlainRegion[i],elf,ElfFile);
+ }
+
+ // Eliminating Duplicated Sections
+ for(int i = ncchset->yaml_set->DefaultSpec.PlainRegionNum - 1; i >= 0; i--){
+ for(int j = i-1; j >= 0; j--){
+ if(Index[i] == Index[j]) Index[i] = 0;
+ }
+ }
+
+ /* Calculating Total Size of Data */
+ u64 TotalSize = 0;
+ for(int i = 0; i < ncchset->yaml_set->DefaultSpec.PlainRegionNum; i++){
+ TotalSize += elf->Sections[Index[i]].Size;
+ }
+
+ /* Creating Output Buffer */
+ ncchset->Sections.PlainRegion.size = align_value(TotalSize,ncchset->Options.MediaSize);
+ ncchset->Sections.PlainRegion.buffer = malloc(ncchset->Sections.PlainRegion.size);
+ if(!ncchset->Sections.PlainRegion.buffer) {fprintf(stderr,"[ELF ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ memset(ncchset->Sections.PlainRegion.buffer,0,ncchset->Sections.PlainRegion.size);
+
+ /* Storing Sections */
+ u64 pos = 0;
+ for(int i = 0; i < ncchset->yaml_set->DefaultSpec.PlainRegionNum; i++){
+ memcpy((ncchset->Sections.PlainRegion.buffer+pos),elf->Sections[Index[i]].Ptr,elf->Sections[Index[i]].Size);
+ pos += elf->Sections[Index[i]].Size;
+ }
+ return 0;
+}
+
+int CreateExeFsCode(ElfContext *elf, u8 *ElfFile, ncch_settings *ncchset)
+{
+ /* Getting Code Segments */
+ CodeSegment Text;
+ memset(&Text,0,sizeof(CodeSegment));
+ CodeSegment RO;
+ memset(&RO,0,sizeof(CodeSegment));
+ CodeSegment Data;
+ memset(&Data,0,sizeof(CodeSegment));
+
+ int result = CreateCodeSegmentFromElf(&Text,elf,ElfFile,ncchset->yaml_set->DefaultSpec.ExeFs.Text,ncchset->yaml_set->DefaultSpec.ExeFs.TextNum);
+ if(result) return result;
+ result = CreateCodeSegmentFromElf(&RO,elf,ElfFile,ncchset->yaml_set->DefaultSpec.ExeFs.ReadOnly,ncchset->yaml_set->DefaultSpec.ExeFs.ReadOnlyNum);
+ if(result) return result;
+ result = CreateCodeSegmentFromElf(&Data,elf,ElfFile,ncchset->yaml_set->DefaultSpec.ExeFs.ReadWrite,ncchset->yaml_set->DefaultSpec.ExeFs.ReadWriteNum);
+ if(result) return result;
+
+ /* Allocating Buffer for ExeFs Code */
+ u32 size = (Text.MaxPageNum + RO.MaxPageNum + Data.MaxPageNum)*elf->PageSize;
+ u8 *code = malloc(size);
+
+ /* Writing Code into Buffer */
+ u8 *TextPos = (code + 0);
+ u8 *ROPos = (code + Text.MaxPageNum*elf->PageSize);
+ u8 *DataPos = (code + (Text.MaxPageNum + RO.MaxPageNum)*elf->PageSize);
+ if(Text.Size) memcpy(TextPos,Text.Data,Text.Size);
+ if(RO.Size) memcpy(ROPos,RO.Data,RO.Size);
+ if(Data.Size) memcpy(DataPos,Data.Data,Data.Size);
+
+
+ /* Compressing If needed */
+ if(ncchset->Options.CompressCode){
+ u32 new_len;
+ ncchset->ExeFs_Sections.Code.buffer = BLZ_Code(code,size,&new_len,BLZ_NORMAL);
+ ncchset->ExeFs_Sections.Code.size = new_len;
+ free(code);
+ }
+ else{
+ ncchset->ExeFs_Sections.Code.size = size;
+ ncchset->ExeFs_Sections.Code.buffer = code;
+ }
+
+ /* Setting CodeSegment Data and freeing original buffers */
+ ncchset->CodeDetails.TextAddress = Text.Address;
+ ncchset->CodeDetails.TextMaxPages = Text.MaxPageNum;
+ ncchset->CodeDetails.TextSize = Text.Size;
+ if(Text.Size) free(Text.Data);
+
+ ncchset->CodeDetails.ROAddress = RO.Address;
+ ncchset->CodeDetails.ROMaxPages = RO.MaxPageNum;
+ ncchset->CodeDetails.ROSize = RO.Size;
+ if(RO.Size) free(RO.Data);
+
+ ncchset->CodeDetails.DataAddress = Data.Address;
+ ncchset->CodeDetails.DataMaxPages = Data.MaxPageNum;
+ ncchset->CodeDetails.DataSize = Data.Size;
+ if(Data.Size) free(Data.Data);
+
+ /* Return */
+ return 0;
+}
+
+int CreateCodeSegmentFromElf(CodeSegment *out, ElfContext *elf, u8 *ElfFile, char **Names, u32 NameNum)
+{
+ u16 ContinuousSegmentNum = 0;
+ memset(out,0,sizeof(CodeSegment));
+ ElfSegment **ContinuousSegments = GetContinuousSegments(&ContinuousSegmentNum,elf,Names,NameNum);
+ if (ContinuousSegments == NULL){
+ if(!ContinuousSegmentNum) // Nothing Was Found
+ return 0;
+ else // Error with found segments
+ return ELF_SEGMENTS_NOT_CONTINUOUS;
+ }
+
+ /* Getting Segment Size/Settings */
+ u32 vAddr = 0;
+ u32 memorySize = 0;
+ for(int i = 0; i < ContinuousSegmentNum; i++){
+ if (i==0){
+ vAddr = ContinuousSegments[i]->VAddr;
+ }
+ else{ // Add rounded size from previous segment
+ u32 num = ContinuousSegments[i]->VAddr - (vAddr + memorySize);
+ memorySize += num;
+ }
+
+ memorySize += ContinuousSegments[i]->Header->SizeInMemory;
+ for (int j = 0; j < ContinuousSegments[i]->SectionNum; j++){
+ ElfSectionEntry *Section = &ContinuousSegments[i]->Sections[j];
+ if (IsBss(Section) && j == (ContinuousSegments[i]->SectionNum-1))
+ memorySize -= Section->Size;
+ }
+ }
+
+ // For Check
+#ifdef ELF_DEBUG
+ printf("Address: 0x%x\n",vAddr);
+ printf("Size: 0x%x\n",memorySize);
+#endif
+
+ out->Address = vAddr;
+ out->Size = memorySize;
+ out->MaxPageNum = SizeToPage(memorySize,elf);
+ out->Data = malloc(memorySize);
+
+ /* Writing Segment to Buffer */
+ vAddr = 0;
+ memorySize = 0;
+ for(int i = 0; i < ContinuousSegmentNum; i++){
+ if (i==0){
+ vAddr = ContinuousSegments[i]->VAddr;
+ }
+ else{
+ u32 num = ContinuousSegments[i]->VAddr - (vAddr + memorySize);
+ memorySize += num;
+ }
+ u32 size = 0;
+ for (int j = 0; j < ContinuousSegments[i]->SectionNum; j++){
+ ElfSectionEntry *Section = &ContinuousSegments[i]->Sections[j];
+ if (!IsBss(Section)){
+ u8 *pos = (out->Data + memorySize + size);
+ memcpy(pos,Section->Ptr,Section->Size);
+ size += Section->Size;
+ }
+
+ else if (j == (ContinuousSegments[i]->SectionNum-1))
+ memorySize -= Section->Size;
+ else
+ size += Section->Size;
+ }
+ }
+
+ free(ContinuousSegments);
+ return 0;
+}
+
+
+ElfSegment** GetContinuousSegments(u16 *ContinuousSegmentNum, ElfContext *elf, char **Names, u32 NameNum)
+{
+ u16 SegmentNum = 0;
+ ElfSegment **Segments = GetSegments(&SegmentNum, elf, Names, NameNum);
+ if (Segments == NULL || SegmentNum == 0){ // No Segments for the names were found
+ //printf("Not Found Segment\n");
+ return NULL;
+ }
+
+ if (SegmentNum == 1){ //Return as there is no need to check
+ *ContinuousSegmentNum = SegmentNum;
+ return Segments;
+ }
+
+ u32 vAddr = Segments[0]->VAddr + Segments[0]->Header->SizeInMemory;
+ for (int i = 1; i < SegmentNum; i++){
+ if (Segments[i]->VAddr != (u32)align_value(vAddr,Segments[i]->Header->Alignment)){ //Each Segment must start after each other
+ fprintf(stderr,"[ELF ERROR] %s segment and %s segment are not continuous\n", Segments[i]->Name, Segments[i - 1]->Name);
+ free(Segments);
+ *ContinuousSegmentNum = 0xffff; // Signify to function that an error occured
+ return NULL;
+ }
+ }
+ *ContinuousSegmentNum = SegmentNum;
+ return Segments;
+}
+
+
+ElfSegment** GetSegments(u16 *SegmentNum, ElfContext *elf, char **Names, u32 NameNum)
+{
+ if (Names == NULL)
+ {
+ return NULL;
+ }
+
+ ElfSegment **Segments = malloc(sizeof(ElfSegment*)*NameNum);
+ *SegmentNum = 0; // There can be a max of NameNum Segments, however, they might not all exist
+ for (int i = 0; i < NameNum; i++){
+ for(int j = 0; j < elf->ActiveSegments; j++){
+ if(strcmp(Names[i],elf->Segments[j].Name) == 0){ // If there is a match, store Segment data pointer & increment index
+ Segments[*SegmentNum] = &elf->Segments[j];
+ *SegmentNum = *SegmentNum + 1;
+ }
+ }
+ }
+ return Segments;
+}
+
+// ELF Functions
+
+int GetElfContext(ElfContext *elf, u8 *ElfFile)
+{
+ if(u8_to_u32(ElfFile,BE) != ELF_MAGIC) return NOT_ELF_FILE;
+
+ elf->Is64bit = (ElfFile[4] == elf_64_bit);
+ elf->IsLittleEndian = (ElfFile[5] == elf_little_endian);
+
+ int result = ReadElfHdr(elf,ElfFile);
+ if(result) return result;
+
+ result = GetElfSectionEntries(elf,ElfFile);
+ if(result) return result;
+
+ result = GetElfProgramEntries(elf,ElfFile);
+ if(result) return result;
+
+ result = CreateElfSegments(elf,ElfFile);
+ if(result) return result;
+
+ return 0;
+}
+
+int GetElfSectionEntries(ElfContext *elf, u8 *ElfFile)
+{
+ elf->Sections = malloc(sizeof(ElfSectionEntry)*elf->SectionTableEntryCount);
+ if(!elf->Sections) {fprintf(stderr,"[ELF ERROR] MEM ERROR\n"); return MEM_ERROR;}
+
+ for(int i = 0; i < elf->SectionTableEntryCount; i++){
+ elf->Sections[i].Name = GetELFSectionEntryName(i,elf,ElfFile);
+ elf->Sections[i].Type = GetELFSectionEntryType(i,elf,ElfFile);
+ elf->Sections[i].Flags = GetELFSectionEntryFlags(i,elf,ElfFile);
+ elf->Sections[i].Ptr = GetELFSectionEntry(i,elf,ElfFile);
+ elf->Sections[i].OffsetInFile = GetELFSectionEntryFileOffset(i,elf,ElfFile);
+ elf->Sections[i].Size = GetELFSectionEntrySize(i,elf,ElfFile);
+ elf->Sections[i].Address = GetELFSectionEntryAddress(i,elf,ElfFile);
+ elf->Sections[i].Alignment = GetELFSectionEntryAlignment(i,elf,ElfFile);
+ }
+ return 0;
+}
+
+int GetElfProgramEntries(ElfContext *elf, u8 *ElfFile)
+{
+ elf->ProgramHeaders = malloc(sizeof(ElfProgramEntry)*elf->ProgramTableEntryCount);
+ if(!elf->ProgramHeaders) {fprintf(stderr,"[ELF ERROR] MEM ERROR\n"); return MEM_ERROR;}
+
+ for(int i = 0; i < elf->ProgramTableEntryCount; i++){
+ elf->ProgramHeaders[i].Type = GetELFProgramEntryType(i,elf,ElfFile);
+ elf->ProgramHeaders[i].Flags = GetELFProgramEntryFlags(i,elf,ElfFile);
+ elf->ProgramHeaders[i].Ptr = GetELFProgramEntry(i,elf,ElfFile);
+ elf->ProgramHeaders[i].OffsetInFile = GetELFProgramEntryFileOffset(i,elf,ElfFile);
+ elf->ProgramHeaders[i].SizeInFile = GetELFProgramEntryFileSize(i,elf,ElfFile);
+ elf->ProgramHeaders[i].PhysicalAddress = GetELFProgramEntryPAddress(i,elf,ElfFile);
+ elf->ProgramHeaders[i].VirtualAddress = GetELFProgramEntryVAddress(i,elf,ElfFile);
+ elf->ProgramHeaders[i].SizeInMemory = GetELFProgramEntryMemorySize(i,elf,ElfFile);
+ elf->ProgramHeaders[i].Alignment = GetELFProgramEntryAlignment(i,elf,ElfFile);
+ }
+
+ return 0;
+}
+
+void PrintElfContext(ElfContext *elf, u8 *ElfFile)
+{
+ printf("[+] Basic Details\n");
+ printf(" Class: %s\n",elf->Is64bit ? "64-bit" : "32-bit");
+ printf(" Data: %s\n",elf->IsLittleEndian ? "Little Endian" : "Big Endian");
+ printf("\n[+] Program Table Data\n");
+ printf(" Offset: 0x%lx\n",elf->ProgramTableOffset);
+ printf(" Size: 0x%x\n",elf->ProgramTableEntrySize);
+ printf(" Count: 0x%x\n",elf->ProgramTableEntryCount);
+ printf("\n[+] Section Table Data\n");
+ printf(" Offset: 0x%lx\n",elf->SectionTableOffset);
+ printf(" Size: 0x%x\n",elf->SectionTableEntrySize);
+ printf(" Count: 0x%x\n",elf->SectionTableEntryCount);
+ printf(" Lable Index: 0x%x\n",elf->SectionHeaderNameEntryIndex);
+ for(int i = 0; i < elf->ActiveSegments; i++){
+ printf(" Segment [%d][%s]\n",i,elf->Segments[i].Name);
+ printf(" > Size : 0x%x\n",elf->Segments[i].Header->SizeInFile);
+ printf(" > Address : 0x%x\n",elf->Segments[i].VAddr);
+ printf(" > Sections : %d\n",elf->Segments[i].SectionNum);
+ for(int j = 0; j < elf->Segments[i].SectionNum; j++){
+ printf(" > Section [%d][%s]\n",j,elf->Segments[i].Sections[j].Name);
+ }
+
+ /*
+ char outpath[100];
+ memset(&outpath,0,100);
+ sprintf(outpath,"%s.bin",elf->Sections[i].Name);
+ chdir("elfsections");
+ FILE *tmp = fopen(outpath,"wb");
+ WriteBuffer(elf->Sections[i].Ptr,elf->Sections[i].Size,0,tmp);
+ fclose(tmp);
+ chdir("..");
+ */
+ }
+
+}
+
+int ReadElfHdr(ElfContext *elf, u8 *ElfFile)
+{
+ if(elf->Is64bit){
+ elf_64_hdr *hdr = (elf_64_hdr*)ElfFile;
+
+ u16 Architecture = u8_to_u16(hdr->TargetArchitecture,elf->IsLittleEndian);
+ u16 Type = u8_to_u16(hdr->Type,elf->IsLittleEndian);
+ if(Architecture != elf_arm) return NOT_ARM_ELF;
+ if(Type != elf_executeable) return NON_EXECUTABLE_ELF;
+
+ elf->ProgramTableOffset = u8_to_u64(hdr->ProgramHeaderTableOffset,elf->IsLittleEndian);
+ elf->ProgramTableEntrySize = u8_to_u16(hdr->ProgramHeaderEntrySize,elf->IsLittleEndian);
+ elf->ProgramTableEntryCount = u8_to_u16(hdr->ProgramHeaderEntryCount,elf->IsLittleEndian);
+
+ elf->SectionTableOffset = u8_to_u64(hdr->SectionHeaderTableOffset,elf->IsLittleEndian);
+ elf->SectionTableEntrySize = u8_to_u16(hdr->SectionTableEntrySize,elf->IsLittleEndian);
+ elf->SectionTableEntryCount = u8_to_u16(hdr->SectionHeaderEntryCount,elf->IsLittleEndian);
+
+ elf->SectionHeaderNameEntryIndex = u8_to_u16(hdr->SectionHeaderNameEntryIndex,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_hdr *hdr = (elf_32_hdr*)ElfFile;
+
+ u16 Architecture = u8_to_u16(hdr->TargetArchitecture,elf->IsLittleEndian);
+ u16 Type = u8_to_u16(hdr->Type,elf->IsLittleEndian);
+ if(Architecture != elf_arm) return NOT_ARM_ELF;
+ if(Type != elf_executeable) return NON_EXECUTABLE_ELF;
+
+ elf->ProgramTableOffset = u8_to_u32(hdr->ProgramHeaderTableOffset,elf->IsLittleEndian);
+ elf->ProgramTableEntrySize = u8_to_u16(hdr->ProgramHeaderEntrySize,elf->IsLittleEndian);
+ elf->ProgramTableEntryCount = u8_to_u16(hdr->ProgramHeaderEntryCount,elf->IsLittleEndian);
+
+ elf->SectionTableOffset = u8_to_u32(hdr->SectionHeaderTableOffset,elf->IsLittleEndian);
+ elf->SectionTableEntrySize = u8_to_u16(hdr->SectionTableEntrySize,elf->IsLittleEndian);
+ elf->SectionTableEntryCount = u8_to_u16(hdr->SectionHeaderEntryCount,elf->IsLittleEndian);
+
+ elf->SectionHeaderNameEntryIndex = u8_to_u16(hdr->SectionHeaderNameEntryIndex,elf->IsLittleEndian);
+ }
+ return 0;
+}
+
+/* Section Hdr Functions */
+
+u8* GetELFSectionHeader(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->SectionTableEntryCount) return NULL;
+
+ return (ElfFile + elf->SectionTableOffset + elf->SectionTableEntrySize*Index);
+}
+
+u8* GetELFSectionEntry(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->SectionTableEntryCount) return NULL;
+
+ return (u8*) (ElfFile + GetELFSectionEntryFileOffset(Index,elf,ElfFile));
+}
+
+char* GetELFSectionEntryName(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->SectionTableEntryCount) return 0;
+
+ u64 NameIndex = 0;
+ if(elf->Is64bit){
+ elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(Index,elf,ElfFile);
+ NameIndex = u8_to_u64(shdr->sh_name,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(Index,elf,ElfFile);
+ NameIndex = u8_to_u32(shdr->sh_name,elf->IsLittleEndian);
+ }
+
+ u8 *NameTable = GetELFSectionEntry(elf->SectionHeaderNameEntryIndex,elf,ElfFile);
+
+ return (char*)(NameTable+NameIndex);
+}
+
+u64 GetELFSectionEntryType(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->SectionTableEntryCount) return 0;
+
+ if(elf->Is64bit){
+ elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(Index,elf,ElfFile);
+ return u8_to_u64(shdr->sh_type,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(Index,elf,ElfFile);
+ return u8_to_u32(shdr->sh_type,elf->IsLittleEndian);
+ }
+
+ return 0;
+}
+
+u64 GetELFSectionEntryFlags(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->SectionTableEntryCount) return 0;
+
+ if(elf->Is64bit){
+ elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(Index,elf,ElfFile);
+ return u8_to_u64(shdr->sh_flags,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(Index,elf,ElfFile);
+ return u8_to_u32(shdr->sh_flags,elf->IsLittleEndian);
+ }
+
+ return 0;
+}
+
+u64 GetELFSectionEntryAddress(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->SectionTableEntryCount) return 0;
+
+ if(elf->Is64bit){
+ elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(Index,elf,ElfFile);
+ return u8_to_u64(shdr->sh_addr,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(Index,elf,ElfFile);
+ return u8_to_u32(shdr->sh_addr,elf->IsLittleEndian);
+ }
+
+ return 0;
+}
+
+u64 GetELFSectionEntryFileOffset(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->SectionTableEntryCount) return 0;
+
+ if(elf->Is64bit){
+ elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(Index,elf,ElfFile);
+ return u8_to_u64(shdr->sh_offset,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(Index,elf,ElfFile);
+ return u8_to_u32(shdr->sh_offset,elf->IsLittleEndian);
+ }
+
+ return 0;
+}
+
+u64 GetELFSectionEntrySize(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->SectionTableEntryCount) return 0;
+
+ if(elf->Is64bit){
+ elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(Index,elf,ElfFile);
+ return u8_to_u64(shdr->sh_size,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(Index,elf,ElfFile);
+ return u8_to_u32(shdr->sh_size,elf->IsLittleEndian);
+ }
+
+ return 0;
+}
+
+u64 GetELFSectionEntryAlignment(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->SectionTableEntryCount) return 0;
+
+ if(elf->Is64bit){
+ elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(Index,elf,ElfFile);
+ return u8_to_u64(shdr->sh_addralign,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(Index,elf,ElfFile);
+ return u8_to_u32(shdr->sh_addralign,elf->IsLittleEndian);
+ }
+
+ return 0;
+}
+
+
+u16 GetElfSectionIndexFromName(char *Name, ElfContext *elf, u8 *ElfFile)
+{
+ for(int i = 0; i < elf->SectionTableEntryCount; i++){
+ if(strcmp(Name,elf->Sections[i].Name) == 0) return i;
+ }
+ return 0; // Assuming 0 is always empty
+}
+
+bool IsBss(ElfSectionEntry *Section)
+{
+ if(Section->Type == 8 && Section->Flags == 3)
+ return true;
+ return false;
+}
+
+bool IsData(ElfSectionEntry *Section)
+{
+ if(Section->Type == 1 && Section->Flags == 3)
+ return true;
+ return false;
+}
+
+bool IsRO(ElfSectionEntry *Section)
+{
+ if(Section->Type == 1 && Section->Flags == 2)
+ return true;
+ return false;
+}
+
+bool IsText(ElfSectionEntry *Section)
+{
+ if(Section->Type == 1 && Section->Flags == 6)
+ return true;
+ return false;
+}
+
+/* ProgramHeader Functions */
+
+u8* GetELFProgramHeader(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->ProgramTableEntryCount) return NULL;
+
+ return (ElfFile + elf->ProgramTableOffset + elf->ProgramTableEntrySize*Index);
+}
+
+u8* GetELFProgramEntry(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->ProgramTableEntryCount) return NULL;
+
+ return (u8*) (ElfFile + GetELFProgramEntryFileOffset(Index,elf,ElfFile));
+
+ return NULL;
+}
+
+u64 GetELFProgramEntryType(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->ProgramTableEntryCount) return 0;
+
+ if(elf->Is64bit){
+ elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u64(phdr->p_type,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u32(phdr->p_type,elf->IsLittleEndian);
+ }
+
+ return 0;
+}
+
+u64 GetELFProgramEntryFlags(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->ProgramTableEntryCount) return 0;
+
+ if(elf->Is64bit){
+ elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u64(phdr->p_flags,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u32(phdr->p_flags,elf->IsLittleEndian);
+ }
+
+ return 0;
+}
+
+u64 GetELFProgramEntryFileSize(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->ProgramTableEntryCount) return 0;
+
+ if(elf->Is64bit){
+ elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u64(phdr->p_filesz,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u32(phdr->p_filesz,elf->IsLittleEndian);
+ }
+
+ return 0;
+}
+
+u64 GetELFProgramEntryFileOffset(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->ProgramTableEntryCount) return 0;
+
+ if(elf->Is64bit){
+ elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u64(phdr->p_offset,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u32(phdr->p_offset,elf->IsLittleEndian);
+ }
+
+ return 0;
+}
+
+u64 GetELFProgramEntryMemorySize(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->ProgramTableEntryCount) return 0;
+
+ if(elf->Is64bit){
+ elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u64(phdr->p_memsz,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u32(phdr->p_memsz,elf->IsLittleEndian);
+ }
+
+ return 0;
+}
+
+u64 GetELFProgramEntryVAddress(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->ProgramTableEntryCount) return 0;
+
+ if(elf->Is64bit){
+ elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u64(phdr->p_vaddr,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u32(phdr->p_vaddr,elf->IsLittleEndian);
+ }
+
+ return 0;
+}
+
+u64 GetELFProgramEntryPAddress(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->ProgramTableEntryCount) return 0;
+
+ if(elf->Is64bit){
+ elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u64(phdr->p_paddr,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u32(phdr->p_paddr,elf->IsLittleEndian);
+ }
+
+ return 0;
+}
+
+
+u64 GetELFProgramEntryAlignment(u16 Index, ElfContext *elf, u8 *ElfFile)
+{
+ if(Index >= elf->ProgramTableEntryCount) return 0;
+
+ if(elf->Is64bit){
+ elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u64(phdr->p_align,elf->IsLittleEndian);
+ }
+ else{
+ elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(Index,elf,ElfFile);
+ return u8_to_u32(phdr->p_align,elf->IsLittleEndian);
+ }
+
+ return 0;
+}
+
+
+int CreateElfSegments(ElfContext *elf, u8 *ElfFile)
+{
+ int num = 0;
+ // Interate through Each Program Header
+ elf->ActiveSegments = 0;
+ elf->Segments = malloc(sizeof(ElfSegment)*elf->ProgramTableEntryCount);
+ ElfSegment *segment = malloc(sizeof(ElfSegment)); // Temporary Buffer
+ for (int i = 0; i < elf->ProgramTableEntryCount; i++){
+ if (elf->ProgramHeaders[i].SizeInMemory != 0 && elf->ProgramHeaders[i].Type == 1){
+ memset(segment,0,sizeof(ElfSegment));
+
+ bool flag = false;
+ u32 size = 0;
+ u32 vAddr = elf->ProgramHeaders[i].VirtualAddress;
+ u32 memorySize = elf->ProgramHeaders[i].SizeInMemory;
+
+ u16 SectionInfoCapacity = 10;
+ segment->SectionNum = 0;
+ segment->Sections = malloc(sizeof(ElfSectionEntry)*SectionInfoCapacity);
+
+ // Itterate Through Section Headers
+ for (int j = num; j < elf->SectionTableEntryCount; j++){
+ if (!flag){
+ if (elf->Sections[j].Address != vAddr)
+ goto Skip;
+
+ while (j < (int)elf->Sections[j].Size && elf->Sections[j].Address == vAddr && !IsIgnoreSection(elf->Sections[j]))
+ j++;
+
+ j--;
+
+ flag = true;
+ segment->VAddr = elf->Sections[j].Address;
+ segment->Name = elf->Sections[j].Name;
+ }
+
+ if(segment->SectionNum < SectionInfoCapacity)
+ memcpy(&segment->Sections[segment->SectionNum],&elf->Sections[j],sizeof(ElfSectionEntry));
+ else{
+ SectionInfoCapacity = SectionInfoCapacity*2;
+ ElfSectionEntry *tmp = malloc(sizeof(ElfSectionEntry)*SectionInfoCapacity);
+ for(int k = 0; k < segment->SectionNum; k++)
+ memcpy(&tmp[k],&segment->Sections[k],sizeof(ElfSectionEntry));
+ free(segment->Sections);
+ segment->Sections = tmp;
+ memcpy(&segment->Sections[segment->SectionNum],&elf->Sections[j],sizeof(ElfSectionEntry));
+ }
+ segment->SectionNum++;
+
+ size += elf->Sections[j].Size;
+
+ if (size == memorySize)
+ break;
+
+ if (size > memorySize){
+ fprintf(stderr,"[ELF ERROR] Too large section size.\n Segment size = 0x%x\n Section Size = 0x%x\n", memorySize, size);
+ return ELF_SEGMENT_SECTION_SIZE_MISMATCH;
+ }
+ Skip: ;
+ }
+ if(segment->SectionNum){
+ segment->Header = &elf->ProgramHeaders[i];
+ memcpy(&elf->Segments[elf->ActiveSegments],segment,sizeof(ElfSegment));
+ elf->ActiveSegments++;
+ }
+ else{
+ free(segment->Sections);
+ free(segment);
+ fprintf(stderr,"[ELF ERROR] Program Header Has no corresponding Sections, ELF Cannot be proccessed\n");
+ return ELF_SEGMENTS_NOT_FOUND;
+ }
+ }
+ }
+
+ free(segment);
+ return 0;
+}
+
+bool IsIgnoreSection(ElfSectionEntry info)
+{
+ if (info.Address)
+ return false;
+
+ if (info.Type != 1 && info.Type != 0)
+ return true;
+
+ char IgnoreSectionNames[7][20] = { ".debug_abbrev", ".debug_frame", ".debug_info", ".debug_line", ".debug_loc", ".debug_pubnames", ".comment" };
+ for (int i = 0; i < 7; i++){
+ if (strcmp(IgnoreSectionNames[i],info.Name) == 0)
+ return true;
+ }
+ return false;
+
+}
diff --git a/elf.h b/elf.h
new file mode 100644
index 0000000..ece978c
--- /dev/null
+++ b/elf.h
@@ -0,0 +1,87 @@
+#ifndef _ELF_H_
+#define _ELF_H_
+
+typedef enum
+{
+ NOT_ELF_FILE = -10,
+ NOT_ARM_ELF = -11,
+ NON_EXECUTABLE_ELF = -12,
+ ELF_SECTION_NOT_FOUND = -13,
+ NOT_FIND_BSS_SIZE = -14,
+ NOT_FIND_CODE_SECTIONS = -15,
+ ELF_SEGMENT_SECTION_SIZE_MISMATCH = -16,
+ ELF_SEGMENTS_NOT_CONTINUOUS = -17,
+ ELF_SEGMENTS_NOT_FOUND = -18,
+} elf_errors;
+
+typedef struct
+{
+ char *Name;
+ u64 Type;
+ u64 Flags;
+ u8 *Ptr;
+ u64 OffsetInFile;
+ u64 Size;
+ u64 Address;
+ u64 Alignment;
+} ElfSectionEntry;
+
+typedef struct
+{
+ u64 Type;
+ u64 Flags;
+ u8 *Ptr;
+ u64 OffsetInFile;
+ u64 SizeInFile;
+ u64 VirtualAddress;
+ u64 PhysicalAddress;
+ u64 SizeInMemory;
+ u64 Alignment;
+
+} ElfProgramEntry;
+
+typedef struct
+{
+ char *Name;
+ u64 VAddr;
+
+ ElfProgramEntry *Header;
+ u32 SectionNum;
+ ElfSectionEntry *Sections;
+} ElfSegment;
+
+typedef struct
+{
+ u32 Address;
+ u32 Size;
+ u32 MaxPageNum;
+ u8 *Data;
+} CodeSegment;
+
+typedef struct
+{
+ u32 PageSize;
+ bool IsLittleEndian;
+ bool Is64bit;
+
+ u64 ProgramTableOffset;
+ u16 ProgramTableEntrySize;
+ u16 ProgramTableEntryCount;
+
+ u64 SectionTableOffset;
+ u16 SectionTableEntrySize;
+ u16 SectionTableEntryCount;
+
+ u16 SectionHeaderNameEntryIndex;
+
+ ElfSectionEntry *Sections;
+ ElfProgramEntry *ProgramHeaders;
+
+ u16 ActiveSegments;
+ ElfSegment *Segments;
+
+} ElfContext;
+
+#endif
+
+int BuildExeFsCode(ncch_settings *ncchset);
\ No newline at end of file
diff --git a/elf_hdr.h b/elf_hdr.h
new file mode 100644
index 0000000..260f420
--- /dev/null
+++ b/elf_hdr.h
@@ -0,0 +1,177 @@
+#ifndef _ELF_HDR_H_
+#define _ELF_HDR_H_
+
+static const u32 ELF_MAGIC = 0x7f454c46;
+
+typedef enum
+{
+ elf_32_bit = 1,
+ elf_64_bit = 2,
+} elf_bit_format_types;
+
+typedef enum
+{
+ elf_little_endian = 1,
+ elf_big_endian = 2,
+} elf_endianness;
+
+typedef enum
+{
+ elf_relocatable = 1,
+ elf_executeable = 2,
+ elf_shared = 3,
+ elf_core = 4,
+} elf_type;
+
+typedef enum
+{
+ elf_arm = 0x28,
+} elf_target_architecture;
+
+typedef struct
+{
+ u8 Magic[4];
+ u8 BitFormat;
+ u8 Endianness;
+ u8 ELF_Version;
+ u8 OS;
+ u8 Padding_0[8];
+ u8 Type[2];
+ u8 TargetArchitecture[2];
+ u8 Version[4];
+ u8 EntryPoint[4];
+ u8 ProgramHeaderTableOffset[4];
+ u8 SectionHeaderTableOffset[4];
+ u8 Flags[4];
+ u8 HeaderSize[2];
+ u8 ProgramHeaderEntrySize[2];
+ u8 ProgramHeaderEntryCount[2];
+ u8 SectionTableEntrySize[2];
+ u8 SectionHeaderEntryCount[2];
+ u8 SectionHeaderNameEntryIndex[2];
+} elf_32_hdr;
+
+typedef struct
+{
+ u8 Magic[4];
+ u8 BitFormat;
+ u8 Endianness;
+ u8 ELF_Version;
+ u8 OS;
+ u8 Padding_0[8];
+ u8 Type[2];
+ u8 TargetArchitecture[2];
+ u8 Version[4];
+ u8 EntryPoint[8];
+ u8 ProgramHeaderTableOffset[8];
+ u8 SectionHeaderTableOffset[8];
+ u8 Flags[4];
+ u8 HeaderSize[2];
+ u8 ProgramHeaderEntrySize[2];
+ u8 ProgramHeaderEntryCount[2];
+ u8 SectionTableEntrySize[2];
+ u8 SectionHeaderEntryCount[2];
+ u8 SectionHeaderNameEntryIndex[2];
+} elf_64_hdr;
+
+
+/* Section header. */
+
+/* Legal values for sh_type (section type). */
+
+#define SHT_NULL 0 /* Section header table entry unused */
+#define SHT_PROGBITS 1 /* Program data */
+#define SHT_SYMTAB 2 /* Symbol table */
+#define SHT_STRTAB 3 /* String table */
+#define SHT_RELA 4 /* Relocation entries with addends */
+#define SHT_HASH 5 /* Symbol hash table */
+#define SHT_DYNAMIC 6 /* Dynamic linking information */
+#define SHT_NOTE 7 /* Notes */
+#define SHT_NOBITS 8 /* Program space with no data (bss) */
+#define SHT_REL 9 /* Relocation entries, no addends */
+#define SHT_SHLIB 10 /* Reserved */
+#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
+#define SHT_NUM 12 /* Number of defined types. */
+#define SHT_LOOS 0x60000000 /* Start OS-specific */
+#define SHT_LOSUNW 0x6ffffffb /* Sun-specific low bound. */
+#define SHT_SUNW_COMDAT 0x6ffffffb
+#define SHT_SUNW_syminfo 0x6ffffffc
+#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */
+#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */
+#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */
+#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */
+#define SHT_HIOS 0x6fffffff /* End OS-specific type */
+#define SHT_LOPROC 0x70000000 /* Start of processor-specific */
+#define SHT_HIPROC 0x7fffffff /* End of processor-specific */
+#define SHT_LOUSER 0x80000000 /* Start of application-specific */
+#define SHT_HIUSER 0x8fffffff /* End of application-specific */
+
+
+typedef struct
+{
+ u8 sh_name[4]; /* Section name (string tbl index) */
+ u8 sh_type[4]; /* Section type */
+ u8 sh_flags[4]; /* Section flags */
+ u8 sh_addr[4]; /* Section virtual addr at execution */
+ u8 sh_offset[4]; /* Section file offset */
+ u8 sh_size[4]; /* Section size in bytes */
+ u8 sh_link[4]; /* Link to another section */
+ u8 sh_info[4]; /* Additional section information */
+ u8 sh_addralign[4]; /* Section alignment */
+ u8 sh_entsize[4]; /* Entry size if section holds table */
+} elf_32_shdr;
+
+typedef struct
+{
+ u8 sh_name[8]; /* Section name (string tbl index) */
+ u8 sh_type[8]; /* Section type */
+ u8 sh_flags[8]; /* Section flags */
+ u8 sh_addr[8]; /* Section virtual addr at execution */
+ u8 sh_offset[8]; /* Section file offset */
+ u8 sh_size[8]; /* Section size in bytes */
+ u8 sh_link[8]; /* Link to another section */
+ u8 sh_info[8]; /* Additional section information */
+ u8 sh_addralign[8]; /* Section alignment */
+ u8 sh_entsize[8]; /* Entry size if section holds table */
+} elf_64_shdr;
+
+/* Program segment header. */
+
+/* p_type legal values */
+#define PT_NULL 0 /* Program header table entry unused */
+#define PT_LOAD 1 /* Loadable program segment */
+#define PT_DYNAMIC 2 /* Dynamic linking information */
+#define PT_INTERP 3 /* Program interpreter */
+#define PT_NOTE 4 /* Auxiliary information */
+#define PT_SHLIB 5 /* Reserved */
+#define PT_PHDR 6 /* Entry for header table itself */
+#define PT_NUM 7 /* Number of defined types. */
+#define PT_LOOS 0x60000000 /* Start of OS-specific */
+#define PT_HIOS 0x6fffffff /* End of OS-specific */
+#define PT_LOPROC 0x70000000 /* Start of processor-specific */
+#define PT_HIPROC 0x7fffffff /* End of processor-specific */
+
+typedef struct
+{
+ u8 p_type[4]; /* Segment type */
+ u8 p_offset[4]; /* Segment file offset */
+ u8 p_vaddr[4]; /* Segment virtual address */
+ u8 p_paddr[4]; /* Segment physical address */
+ u8 p_filesz[4]; /* Segment size in file */
+ u8 p_memsz[4]; /* Segment size in memory */
+ u8 p_flags[4]; /* Segment flags */
+ u8 p_align[4]; /* Segment alignment */
+} elf_32_phdr;
+
+typedef struct
+{
+ u8 p_type[8]; /* Segment type */
+ u8 p_flags[8]; /* Segment flags */
+ u8 p_offset[8]; /* Segment file offset */
+ u8 p_vaddr[8]; /* Segment virtual address */
+ u8 p_paddr[8]; /* Segment physical address */
+ u8 p_filesz[8]; /* Segment size in file */
+ u8 p_memsz[8]; /* Segment size in memory */
+ u8 p_align[8]; /* Segment alignment */
+} elf_64_phdr;
+#endif
\ No newline at end of file
diff --git a/exefs.c b/exefs.c
new file mode 100644
index 0000000..15dd4ae
--- /dev/null
+++ b/exefs.c
@@ -0,0 +1,179 @@
+#include "lib.h"
+#include "ncch.h"
+#include "exefs.h"
+
+// Private Prototypes
+u32 PredictExeFS_Size(ExeFs_BuildContext *ctx);
+int GenerateExeFS_Header(ExeFs_BuildContext *ctx, u8 *outbuff);
+void InitialiseExeFSContext(ExeFs_BuildContext *ctx);
+void FreeExeFSContext(ExeFs_BuildContext *ctx);
+int ImportDatatoExeFS(ExeFs_BuildContext *ctx, u8 *outbuff);
+int ImportToExeFSContext(ExeFs_BuildContext *ctx, char *lable, u8 *buffer, u32 size);
+
+// ExeFs Build Functions
+int BuildExeFs(ncch_settings *ncchset)
+{
+ /* Intialising ExeFs Build Context */
+ ExeFs_BuildContext *ctx = malloc(sizeof(ExeFs_BuildContext));
+ if(!ctx) {fprintf(stderr,"[EXEFS ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ InitialiseExeFSContext(ctx);
+ ctx->media_unit = ncchset->Options.MediaSize;
+
+ /* Importing ExeFs */
+ if(ncchset->ExeFs_Sections.Code.size)
+ ImportToExeFSContext(ctx,".code",ncchset->ExeFs_Sections.Code.buffer,ncchset->ExeFs_Sections.Code.size);
+ if(ncchset->ExeFs_Sections.Banner.size)
+ ImportToExeFSContext(ctx,"banner",ncchset->ExeFs_Sections.Banner.buffer,ncchset->ExeFs_Sections.Banner.size);
+ if(ncchset->ExeFs_Sections.Icon.size)
+ ImportToExeFSContext(ctx,"icon",ncchset->ExeFs_Sections.Icon.buffer,ncchset->ExeFs_Sections.Icon.size);
+ if(ncchset->Sections.Logo.size && ncchset->Options.IncludeExeFsLogo)
+ ImportToExeFSContext(ctx,"logo",ncchset->Sections.Logo.buffer,ncchset->Sections.Logo.size);
+
+ /* Allocating Memory for ExeFs */
+ ncchset->Sections.ExeFs.size = PredictExeFS_Size(ctx);
+ ncchset->Sections.ExeFs.buffer = malloc(ncchset->Sections.ExeFs.size);
+ if(!ncchset->Sections.ExeFs.buffer){
+ printf("[EXEFS ERROR] Could Not Allocate Memory for ExeFS\n");
+ return Fail;
+ }
+ memset(ncchset->Sections.ExeFs.buffer,0,ncchset->Sections.ExeFs.size);
+
+ /* Generating Header, and writing sections to buffer */
+ GenerateExeFS_Header(ctx,ncchset->Sections.ExeFs.buffer);
+ ImportDatatoExeFS(ctx,ncchset->Sections.ExeFs.buffer);
+
+ /* Finish */
+ FreeExeFSContext(ctx);
+ return 0;
+}
+
+u32 PredictExeFS_Size(ExeFs_BuildContext *ctx)
+{
+ u32 exefs_size = 0x200; // Size of header
+ for(int i = 0; i < ctx->section_count; i++){
+ exefs_size += align_value(ctx->section_size[i],ctx->media_unit);
+ }
+ //exefs_size = align_value(ctx->exefs_size,ctx->media_unit);
+ return exefs_size;
+}
+
+int GenerateExeFS_Header(ExeFs_BuildContext *ctx, u8 *outbuff)
+{
+ for(int i = 0; i < ctx->section_count; i++){
+ if(i == 0)
+ ctx->section_offset[i] = 0;
+ else
+ ctx->section_offset[i] = align_value((ctx->section_offset[i-1]+ctx->section_size[i-1]),ctx->media_unit);
+
+ memcpy(ctx->file_header[i].name,ctx->lable[i],8);
+ u32_to_u8(ctx->file_header[i].offset,ctx->section_offset[i],LE);
+ u32_to_u8(ctx->file_header[i].size,ctx->section_size[i],LE);
+ ctr_sha(ctx->section[i],ctx->section_size[i],ctx->file_hashes[9-i],CTR_SHA_256);
+ }
+ memcpy(outbuff,ctx->file_header,sizeof(ExeFs_FileHeader)*10);
+ memcpy(outbuff+0xc0,ctx->file_hashes,0x20*10);
+ return 0;
+}
+
+void InitialiseExeFSContext(ExeFs_BuildContext *ctx)
+{
+ memset(ctx,0,sizeof(ExeFs_BuildContext));
+}
+
+void FreeExeFSContext(ExeFs_BuildContext *ctx)
+{
+ /*
+ if(ctx->outbuff != NULL)
+ free(ctx->outbuff);
+ for(int i = 0; i < 10; i++){
+ if(ctx->section[i] != NULL)
+ free(ctx->section[i]);
+ }
+ */
+ memset(ctx,0,sizeof(ExeFs_BuildContext));
+ free(ctx);
+}
+
+int ImportDatatoExeFS(ExeFs_BuildContext *ctx, u8 *outbuff)
+{
+ for(int i = 0; i < ctx->section_count; i++){
+ memcpy(outbuff+ctx->section_offset[i]+0x200,ctx->section[i],ctx->section_size[i]);
+ }
+ return 0;
+}
+
+int ImportToExeFSContext(ExeFs_BuildContext *ctx, char *lable, u8 *buffer, u32 size)
+{
+ if(ctx == NULL || lable == NULL || buffer == NULL){
+ printf("[!] PTR ERROR\n");
+ return PTR_ERROR;
+ }
+ if(ctx->section_count >= 10){
+ printf("[!] Maximum ExeFS Capacity Reached\n");
+ return EXEFS_MAX_REACHED;
+ }
+ if(strlen(lable) > 8){
+ printf("[!] ExeFS Section Name: '%s' is too large\n",lable);
+ return EXEFS_SECTION_NAME_ERROR;
+ }
+
+ ctx->section_count++;
+ ctx->section[ctx->section_count - 1] = buffer;
+ ctx->section_size[ctx->section_count - 1] = size;
+ strcpy(ctx->lable[ctx->section_count - 1],lable);
+ return 0;
+}
+
+// ExeFs Read Functions
+bool DoesExeFsSectionExist(char *section, u8 *ExeFs)
+{
+ ExeFs_Header *hdr = (ExeFs_Header*) ExeFs;
+ for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
+ if(strncmp(hdr->SectionHdr[i].name,section,8) == 0) return true;
+ }
+ return false;
+}
+u8* GetExeFsSection(char *section, u8 *ExeFs)
+{
+ ExeFs_Header *hdr = (ExeFs_Header*) ExeFs;
+ for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
+ if(strncmp(hdr->SectionHdr[i].name,section,8) == 0){
+ u32 offset = u8_to_u32(hdr->SectionHdr[i].offset,LE) + sizeof(ExeFs_Header);
+ return (u8*)(ExeFs+offset);
+ }
+ }
+ return NULL;
+}
+
+u8* GetExeFsSectionHash(char *section, u8 *ExeFs)
+{
+ ExeFs_Header *hdr = (ExeFs_Header*) ExeFs;
+ for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
+ if(strncmp(hdr->SectionHdr[i].name,section,8) == 0){
+ return (u8*)(hdr->SectionHashes[MAX_EXEFS_SECTIONS-1-i]);
+ }
+ }
+ return NULL;
+}
+
+u32 GetExeFsSectionSize(char *section, u8 *ExeFs)
+{
+ ExeFs_Header *hdr = (ExeFs_Header*) ExeFs;
+ for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
+ if(strncmp(hdr->SectionHdr[i].name,section,8) == 0){
+ return u8_to_u32(hdr->SectionHdr[i].size,LE);
+ }
+ }
+ return 0;
+}
+
+u32 GetExeFsSectionOffset(char *section, u8 *ExeFs)
+{
+ ExeFs_Header *hdr = (ExeFs_Header*) ExeFs;
+ for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
+ if(strncmp(hdr->SectionHdr[i].name,section,8) == 0){
+ return u8_to_u32(hdr->SectionHdr[i].offset,LE) + sizeof(ExeFs_Header);
+ }
+ }
+ return 0;
+}
\ No newline at end of file
diff --git a/exefs.h b/exefs.h
new file mode 100644
index 0000000..4564fc5
--- /dev/null
+++ b/exefs.h
@@ -0,0 +1,54 @@
+#ifndef _EXEFS_H_
+#define _EXEFS_H_
+
+#define MAX_EXEFS_SECTIONS 10 // DO NOT CHANGE
+
+typedef enum
+{
+ PTR_ERROR = -10,
+ EXEFS_MAX_REACHED = -11,
+ EXEFS_SECTION_NAME_ERROR = -12,
+
+} exefs_errors;
+
+typedef struct
+{
+ char name[8];
+ u8 offset[4];
+ u8 size[4];
+} ExeFs_FileHeader;
+
+typedef struct
+{
+ //Input
+ int section_count;
+ u8 *section[10];
+ u32 section_size[10];
+ u32 section_offset[10];
+ char lable[10][8];
+ u32 media_unit;
+
+ //Working Data
+ ExeFs_FileHeader file_header[10];
+ u8 file_hashes[10][0x20];
+
+} ExeFs_BuildContext;
+
+typedef struct
+{
+ ExeFs_FileHeader SectionHdr[MAX_EXEFS_SECTIONS];
+ u8 Reserved[0x20];
+ u8 SectionHashes[MAX_EXEFS_SECTIONS][0x20];
+} ExeFs_Header;
+
+#endif
+
+/* ExeFs Build Functions */
+int BuildExeFs(ncch_settings *ncchset);
+
+/* ExeFs Read Functions */
+bool DoesExeFsSectionExist(char *section, u8 *ExeFs);
+u8* GetExeFsSection(char *section, u8 *ExeFs);
+u8* GetExeFsSectionHash(char *section, u8 *ExeFs);
+u32 GetExeFsSectionSize(char *section, u8 *ExeFs);
+u32 GetExeFsSectionOffset(char *section, u8 *ExeFs);
diff --git a/exheader.c b/exheader.c
new file mode 100644
index 0000000..61866c0
--- /dev/null
+++ b/exheader.c
@@ -0,0 +1,488 @@
+#include "lib.h"
+#include "ncch.h"
+#include "exheader.h"
+
+#include "titleid.h"
+#include "polarssl\base64.h"
+
+#ifndef RETAIL_FSIGN
+#include "accessdesc_sig.h" // For AccessDesc Presets
+#endif
+
+/* Prototypes */
+void init_ExHeaderSettings(exheader_settings *exhdrset);
+void free_ExHeaderSettings(exheader_settings *exhdrset);
+int get_ExHeaderSettingsFromNcchset(exheader_settings *exhdrset, ncch_settings *ncchset);
+int get_ExHeaderSettingsFromYaml(exheader_settings *exhdrset);
+
+void AdjustBooleans(desc_settings *yaml);
+int get_ExHeaderCodeSetInfo(exhdr_CodeSetInfo *CodeSetInfo, desc_settings *yaml);
+int get_ExHeaderDependencyList(u8 *DependencyList, desc_settings *yaml);
+int get_ExHeaderSystemInfo(exhdr_SystemInfo *SystemInfo, desc_settings *yaml);
+int get_ExHeaderARM11SystemLocalInfo(exhdr_ARM11SystemLocalCapabilities *arm11, desc_settings *yaml);
+int get_ExHeaderARM11KernelInfo(exhdr_ARM11KernelCapabilities *arm11, desc_settings *yaml);
+int get_ExHeaderARM9AccessControlInfo(exhdr_ARM9AccessControlInfo *arm9, desc_settings *yaml);
+
+int set_AccessDesc(exheader_settings *exhdrset, ncch_settings *ncchset);
+
+/* ExHeader Signature Functions */
+int SignAccessDesc(ExtendedHeader_Struct *ExHdr, keys_struct *keys)
+{
+ u8 *AccessDesc = (u8*) &ExHdr->AccessDescriptor.ncchpubkeymodulus;
+ u8 *Signature = (u8*) &ExHdr->AccessDescriptor.signature;
+ return ctr_sig(AccessDesc,0x300,Signature,keys->rsa.AccessDesc_Pub,keys->rsa.AccessDesc_Priv,RSA_2048_SHA256,CTR_RSA_SIGN);
+}
+
+int CheckAccessDescSignature(ExtendedHeader_Struct *ExHdr, keys_struct *keys)
+{
+ u8 *AccessDesc = (u8*) &ExHdr->AccessDescriptor.ncchpubkeymodulus;
+ u8 *Signature = (u8*) &ExHdr->AccessDescriptor.signature;
+ return ctr_sig(AccessDesc,0x300,Signature,keys->rsa.AccessDesc_Pub,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY);
+}
+
+/* ExHeader Build Functions */
+int BuildExHeader(ncch_settings *ncchset)
+{
+ int result = 0;
+
+ exheader_settings *exhdrset = malloc(sizeof(exheader_settings));
+ if(!exhdrset) {fprintf(stderr,"[EXHEADER ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ init_ExHeaderSettings(exhdrset);
+
+ // Get Settings
+ result = get_ExHeaderSettingsFromNcchset(exhdrset,ncchset);
+ if(result) goto finish;
+
+ result = get_ExHeaderSettingsFromYaml(exhdrset);
+ if(result) goto finish;
+
+ result = set_AccessDesc(exhdrset,ncchset);
+ if(result) goto finish;
+
+ memcpy(&exhdrset->ExHdr->ARM11SystemLocalCapabilities.Flags,&exhdrset->ExHdr->AccessDescriptor.ARM11SystemLocalCapabilities.Flags,0x1f8);
+
+finish:
+ if(result) fprintf(stderr,"[EXHEADER ERROR] Failed to create ExHeader\n");
+ free_ExHeaderSettings(exhdrset);
+ return result;
+}
+
+
+void init_ExHeaderSettings(exheader_settings *exhdrset)
+{
+ memset(exhdrset,0,sizeof(exheader_settings));
+}
+
+void free_ExHeaderSettings(exheader_settings *exhdrset)
+{
+ free(exhdrset);
+}
+
+int get_ExHeaderSettingsFromNcchset(exheader_settings *exhdrset, ncch_settings *ncchset)
+{
+ /* Transfer settings */
+ exhdrset->keys = ncchset->keys;
+ exhdrset->yaml = ncchset->yaml_set;
+
+ /* Creating Output Buffer */
+ ncchset->Sections.ExHeader.size = 0x800;
+ ncchset->Sections.ExHeader.buffer = malloc(ncchset->Sections.ExHeader.size);
+ if(!ncchset->Sections.ExHeader.buffer) {fprintf(stderr,"[EXHEADER ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ memset(ncchset->Sections.ExHeader.buffer,0,ncchset->Sections.ExHeader.size);
+
+ /* Import ExHeader template */
+ if(ncchset->ComponentFilePtrs.exheader_size){
+ u32 import_size = min_u64(0x400,ncchset->ComponentFilePtrs.exheader_size);
+ ReadFile_64(ncchset->Sections.ExHeader.buffer,import_size,0,ncchset->ComponentFilePtrs.exheader);
+ }
+
+ /* Create ExHeader Struct for output */
+ exhdrset->ExHdr = (ExtendedHeader_Struct*)ncchset->Sections.ExHeader.buffer;
+
+ /* Set Code Info if Code Section was built not imported */
+ if(ncchset->Options.IsBuildingCodeSection){
+ /* BSS Size */
+ u32_to_u8(exhdrset->ExHdr->CodeSetInfo.BssSize,ncchset->CodeDetails.BSS_Size,LE);
+ /* Data */
+ u32_to_u8(exhdrset->ExHdr->CodeSetInfo.DataSectionInfo.Address,ncchset->CodeDetails.DataAddress,LE);
+ u32_to_u8(exhdrset->ExHdr->CodeSetInfo.DataSectionInfo.CodeSize,ncchset->CodeDetails.DataSize,LE);
+ u32_to_u8(exhdrset->ExHdr->CodeSetInfo.DataSectionInfo.NumMaxPages,ncchset->CodeDetails.DataMaxPages,LE);
+ /* RO */
+ u32_to_u8(exhdrset->ExHdr->CodeSetInfo.ReadOnlySectionInfo.Address,ncchset->CodeDetails.ROAddress,LE);
+ u32_to_u8(exhdrset->ExHdr->CodeSetInfo.ReadOnlySectionInfo.CodeSize,ncchset->CodeDetails.ROSize,LE);
+ u32_to_u8(exhdrset->ExHdr->CodeSetInfo.ReadOnlySectionInfo.NumMaxPages,ncchset->CodeDetails.ROMaxPages,LE);
+ /* Text */
+ u32_to_u8(exhdrset->ExHdr->CodeSetInfo.TextSectionInfo.Address,ncchset->CodeDetails.TextAddress,LE);
+ u32_to_u8(exhdrset->ExHdr->CodeSetInfo.TextSectionInfo.CodeSize,ncchset->CodeDetails.TextSize,LE);
+ u32_to_u8(exhdrset->ExHdr->CodeSetInfo.TextSectionInfo.NumMaxPages,ncchset->CodeDetails.TextMaxPages,LE);
+ }
+
+ /* Set Simple Flags */
+ if(ncchset->Options.CompressCode)
+ exhdrset->ExHdr->CodeSetInfo.Flags.flag |= ExeFsCodeCompress;
+ if(ncchset->Options.UseOnSD)
+ exhdrset->ExHdr->CodeSetInfo.Flags.flag |= RetailSDAppFlag;
+
+ return 0;
+}
+
+int get_ExHeaderSettingsFromYaml(exheader_settings *exhdrset)
+{
+ AdjustBooleans(exhdrset->yaml);
+
+ int result = 0;
+ result = get_ExHeaderCodeSetInfo(&exhdrset->ExHdr->CodeSetInfo, exhdrset->yaml);
+ if(result) goto finish;
+
+ result = get_ExHeaderDependencyList((u8*)&exhdrset->ExHdr->DependencyList[0], exhdrset->yaml);
+ if(result) goto finish;
+
+ result = get_ExHeaderSystemInfo(&exhdrset->ExHdr->SystemInfo, exhdrset->yaml);
+ if(result) goto finish;
+
+ result = get_ExHeaderARM11SystemLocalInfo(&exhdrset->ExHdr->ARM11SystemLocalCapabilities, exhdrset->yaml);
+ if(result) goto finish;
+
+ result = get_ExHeaderARM11KernelInfo(&exhdrset->ExHdr->ARM11KernelCapabilities, exhdrset->yaml);
+ if(result) goto finish;
+
+ result = get_ExHeaderARM9AccessControlInfo(&exhdrset->ExHdr->ARM9AccessControlInfo, exhdrset->yaml);
+ if(result) goto finish;
+
+finish:
+ return result;
+}
+
+void AdjustBooleans(desc_settings *yaml)
+{
+ if(yaml->DefaultSpec.AccessControlInfo.DisableDebug == -1) yaml->DefaultSpec.AccessControlInfo.DisableDebug = 0;
+ if(yaml->DefaultSpec.AccessControlInfo.EnableForceDebug == -1) yaml->DefaultSpec.AccessControlInfo.EnableForceDebug = 0;
+ if(yaml->DefaultSpec.AccessControlInfo.CanWriteSharedPage == -1) yaml->DefaultSpec.AccessControlInfo.CanWriteSharedPage = 0;
+ if(yaml->DefaultSpec.AccessControlInfo.CanUsePrivilegedPriority == -1) yaml->DefaultSpec.AccessControlInfo.CanUsePrivilegedPriority = 0;
+ if(yaml->DefaultSpec.AccessControlInfo.CanUseNonAlphabetAndNumber == -1) yaml->DefaultSpec.AccessControlInfo.CanUseNonAlphabetAndNumber = 0;
+ if(yaml->DefaultSpec.AccessControlInfo.PermitMainFunctionArgument == -1) yaml->DefaultSpec.AccessControlInfo.PermitMainFunctionArgument = 0;
+ if(yaml->DefaultSpec.AccessControlInfo.CanShareDeviceMemory == -1) yaml->DefaultSpec.AccessControlInfo.CanShareDeviceMemory = 0;
+ if(yaml->DefaultSpec.AccessControlInfo.UseOtherVariationSaveData == -1) yaml->DefaultSpec.AccessControlInfo.UseOtherVariationSaveData = 0;
+ if(yaml->DefaultSpec.AccessControlInfo.UseExtSaveData == -1) yaml->DefaultSpec.AccessControlInfo.UseExtSaveData = 0;
+ if(yaml->DefaultSpec.AccessControlInfo.RunnableOnSleep == -1) yaml->DefaultSpec.AccessControlInfo.RunnableOnSleep = 0;
+ if(yaml->DefaultSpec.AccessControlInfo.SpecialMemoryArrange == -1) yaml->DefaultSpec.AccessControlInfo.SpecialMemoryArrange = 0;
+}
+
+int get_ExHeaderCodeSetInfo(exhdr_CodeSetInfo *CodeSetInfo, desc_settings *yaml)
+{
+ /* Name */
+ if(yaml->DefaultSpec.BasicInfo.Title){
+ if(strlen(yaml->DefaultSpec.BasicInfo.Title) > 8){
+ fprintf(stderr,"[EXHEADER ERROR] Parameter Too Long 'BasicInfo/Title'\n");
+ return EXHDR_BAD_YAML_OPT;
+ }
+ strcpy((char*)CodeSetInfo->Name,yaml->DefaultSpec.BasicInfo.Title);
+ }
+ else{
+ fprintf(stderr,"[EXHEADER ERROR] Parameter Not Found: 'BasicInfo/Title'\n");
+ }
+ /* Stack Size */
+ if(yaml->DefaultSpec.SystemControlInfo.StackSize){
+ u32 StackSize = strtoul(yaml->DefaultSpec.SystemControlInfo.StackSize,NULL,0);
+ u32_to_u8(CodeSetInfo->StackSize,StackSize,LE);
+ }
+ else{
+ fprintf(stderr,"[EXHEADER ERROR] Parameter Not Found: 'SystemControlInfo/StackSize'\n");
+ }
+ /* Remaster Version */
+ if(yaml->DefaultSpec.SystemControlInfo.RemasterVersion){
+ u16 RemasterVersion = strtol(yaml->DefaultSpec.SystemControlInfo.RemasterVersion,NULL,0);
+ u16_to_u8(CodeSetInfo->Flags.remasterVersion,RemasterVersion,LE);
+ }
+ else{
+ u16_to_u8(CodeSetInfo->Flags.remasterVersion,0,LE);
+ }
+ return 0;
+}
+
+int get_ExHeaderDependencyList(u8 *DependencyList, desc_settings *yaml)
+{
+ if(yaml->DefaultSpec.SystemControlInfo.DependencyNum > 0x30){
+ fprintf(stderr,"[EXHEADER ERROR] Too Many Dependency IDs\n");
+ return EXHDR_BAD_YAML_OPT;
+ }
+ for(int i = 0; i < yaml->DefaultSpec.SystemControlInfo.DependencyNum; i++){
+ u8 *pos = (DependencyList + 0x8*i);
+ u64 TitleID = strtoull(yaml->DefaultSpec.SystemControlInfo.Dependency[i],NULL,0);
+ u64_to_u8(pos,TitleID,LE);
+ }
+ return 0;
+}
+
+int get_ExHeaderSystemInfo(exhdr_SystemInfo *SystemInfo, desc_settings *yaml)
+{
+ /* SaveDataSize */
+ if(yaml->DefaultSpec.Rom.SaveDataSize){
+ u64 SaveDataSize = strtoull(yaml->DefaultSpec.Rom.SaveDataSize,NULL,10);
+ if(strstr(yaml->DefaultSpec.Rom.SaveDataSize,"K")){
+ char *str = strstr(yaml->DefaultSpec.Rom.SaveDataSize,"K");
+ if(strcmp(str,"K") == 0 || strcmp(str,"KB") == 0 ){
+ SaveDataSize = SaveDataSize*KB;
+ }
+ }
+ else if(strstr(yaml->DefaultSpec.Rom.SaveDataSize,"M")){
+ char *str = strstr(yaml->DefaultSpec.Rom.SaveDataSize,"M");
+ if(strcmp(str,"M") == 0 || strcmp(str,"MB") == 0 ){
+ SaveDataSize = SaveDataSize*MB;
+ }
+ }
+ else if(strstr(yaml->DefaultSpec.Rom.SaveDataSize,"G")){
+ char *str = strstr(yaml->DefaultSpec.Rom.SaveDataSize,"G");
+ if(strcmp(str,"G") == 0 || strcmp(str,"GB") == 0 ){
+ SaveDataSize = SaveDataSize*GB;
+ }
+ }
+ else{
+ fprintf(stderr,"[EXHEADER ERROR] Invalid save data size format.\n");
+ return EXHDR_BAD_YAML_OPT;
+ }
+ if((SaveDataSize & 65536) != 0){
+ fprintf(stderr,"[EXHEADER ERROR] Save data size must be aligned to 64K.\n");
+ return EXHDR_BAD_YAML_OPT;
+ }
+ u64_to_u8(SystemInfo->SaveDataSize,SaveDataSize,LE);
+ }
+ else{
+ u64_to_u8(SystemInfo->SaveDataSize,0,LE);
+ }
+ /* Jump Id */
+ if(yaml->DefaultSpec.SystemControlInfo.JumpId){
+ u64 JumpId = strtoull(yaml->DefaultSpec.SystemControlInfo.JumpId,NULL,0);
+ u64_to_u8(SystemInfo->JumpId,JumpId,LE);
+ }
+ else{
+ u64 JumpId = 0;
+ int result = GetProgramID(&JumpId,yaml,false);
+ if(result) return result;
+ u64_to_u8(SystemInfo->JumpId,JumpId,LE);
+ }
+ return 0;
+}
+
+int get_ExHeaderARM11SystemLocalInfo(exhdr_ARM11SystemLocalCapabilities *arm11, desc_settings *yaml)
+{
+ /* Program Id */
+ u64 ProgramId = 0;
+ int result = GetProgramID(&ProgramId,yaml,true);
+ if(result) return result;
+ u64_to_u8(arm11->ProgramId,ProgramId,LE);
+ return 0;
+ /* Flags */
+ //u32_to_u8(
+}
+
+int get_ExHeaderARM11KernelInfo(exhdr_ARM11KernelCapabilities *arm11, desc_settings *yaml)
+{
+ return 0;
+}
+
+int get_ExHeaderARM9AccessControlInfo(exhdr_ARM9AccessControlInfo *arm9, desc_settings *yaml)
+{
+ return 0;
+}
+
+int set_AccessDesc(exheader_settings *exhdrset, ncch_settings *ncchset)
+{
+ switch(ncchset->Options.accessdesc){
+ case auto_gen :
+ /* Set RSA Keys */
+ memcpy(ncchset->CxiRsaKey.PrivK,exhdrset->keys->rsa.CFA_Priv,0x100);
+ memcpy(ncchset->CxiRsaKey.PubK,exhdrset->keys->rsa.CFA_Pub,0x100);
+ memcpy(&exhdrset->ExHdr->AccessDescriptor.ncchpubkeymodulus,exhdrset->keys->rsa.CFA_Pub,0x100);
+ /* Copy Data From ExHeader */
+ memcpy(&exhdrset->ExHdr->AccessDescriptor.ARM11SystemLocalCapabilities,&exhdrset->ExHdr->ARM11SystemLocalCapabilities,sizeof(exhdr_ARM11SystemLocalCapabilities));
+ memcpy(&exhdrset->ExHdr->AccessDescriptor.ARM11KernelCapabilities,&exhdrset->ExHdr->ARM11KernelCapabilities,sizeof(exhdr_ARM11KernelCapabilities));
+ memcpy(&exhdrset->ExHdr->AccessDescriptor.ARM9AccessControlInfo,&exhdrset->ExHdr->ARM9AccessControlInfo,sizeof(exhdr_ARM9AccessControlInfo));
+ /* Sign AccessDesc */
+ return SignAccessDesc(exhdrset->ExHdr,exhdrset->keys);
+#ifndef RETAIL_FSIGN
+ case app :
+ memcpy(ncchset->CxiRsaKey.PrivK,(u8*)App_HdrPrivK,0x100);
+ memcpy(ncchset->CxiRsaKey.PubK,(u8*)App_HdrPubK,0x100);
+ memcpy(&exhdrset->ExHdr->AccessDescriptor.signature,(u8*)App_AcexData,0x400);
+ return 0;
+ case demo :
+ memcpy(ncchset->CxiRsaKey.PrivK,(u8*)Demo_HdrPrivK,0x100);
+ memcpy(ncchset->CxiRsaKey.PubK,(u8*)Demo_HdrPubK,0x100);
+ memcpy(&exhdrset->ExHdr->AccessDescriptor.signature,(u8*)Demo_AcexData,0x400);
+ return 0;
+ case dlp :
+ memcpy(ncchset->CxiRsaKey.PrivK,(u8*)Dlp_HdrPrivK,0x100);
+ memcpy(ncchset->CxiRsaKey.PubK,(u8*)Dlp_HdrPubK,0x100);
+ memcpy(&exhdrset->ExHdr->AccessDescriptor.signature,(u8*)Dlp_AcexData,0x400);
+ return 0;
+ case use_desc_file:
+ /* Yaml Option Sanity Checks */
+ if(!exhdrset->yaml->CommonHeaderKey.Found){
+ fprintf(stderr,"[EXHEADER ERROR] Desc Section 'CommonHeaderKey' not found\n");
+ return COMMON_HEADER_KEY_NOT_FOUND;
+ }
+ if(!exhdrset->yaml->CommonHeaderKey.D){
+ fprintf(stderr,"[EXHEADER ERROR] 'CommonHeaderKey/D' not found\n");
+ return COMMON_HEADER_KEY_NOT_FOUND;
+ }
+ if(strlen(exhdrset->yaml->CommonHeaderKey.D) != 350){
+ fprintf(stderr,"[EXHEADER ERROR] 'CommonHeaderKey/D' has invalid length (%d)\n",strlen(exhdrset->yaml->CommonHeaderKey.D));
+ return COMMON_HEADER_KEY_NOT_FOUND;
+ }
+ if(!exhdrset->yaml->CommonHeaderKey.Modulus){
+ fprintf(stderr,"[EXHEADER ERROR] 'CommonHeaderKey/Modulus' not found\n");
+ return COMMON_HEADER_KEY_NOT_FOUND;
+ }
+ if(strlen(exhdrset->yaml->CommonHeaderKey.Modulus) != 350){
+ fprintf(stderr,"[EXHEADER ERROR] 'CommonHeaderKey/Modulus' has invalid length (%d)\n",strlen(exhdrset->yaml->CommonHeaderKey.Modulus));
+ return COMMON_HEADER_KEY_NOT_FOUND;
+ }
+ if(!exhdrset->yaml->AccessControlDescriptor.AccCtlDescSign){
+ fprintf(stderr,"[EXHEADER ERROR] 'AccessControlDescriptor/Signature' not found\n");
+ return COMMON_HEADER_KEY_NOT_FOUND;
+ }
+ if(strlen(exhdrset->yaml->AccessControlDescriptor.AccCtlDescSign) != 350){
+ fprintf(stderr,"[EXHEADER ERROR] 'AccessControlDescriptor/Signature' has invalid length (%d)\n",strlen(exhdrset->yaml->AccessControlDescriptor.AccCtlDescSign));
+ return COMMON_HEADER_KEY_NOT_FOUND;
+ }
+ if(!exhdrset->yaml->AccessControlDescriptor.AccCtlDescBin){
+ fprintf(stderr,"[EXHEADER ERROR] 'AccessControlDescriptor/Descriptor' not found\n");
+ return COMMON_HEADER_KEY_NOT_FOUND;
+ }
+ if(strlen(exhdrset->yaml->AccessControlDescriptor.AccCtlDescBin) != 696){
+ fprintf(stderr,"[EXHEADER ERROR] 'AccessControlDescriptor/Descriptor' has invalid length (%d)\n",strlen(exhdrset->yaml->AccessControlDescriptor.AccCtlDescBin));
+ return COMMON_HEADER_KEY_NOT_FOUND;
+ }
+ /* Set RSA Keys */
+ int result = 0;
+ u32 out = 0x500;
+ u8 *tmp = malloc(0x500);
+ result = base64_decode(tmp,&out,(const u8*)exhdrset->yaml->CommonHeaderKey.Modulus,strlen(exhdrset->yaml->CommonHeaderKey.Modulus));
+ if(result) goto finish;
+ memcpy(ncchset->CxiRsaKey.PubK,tmp,0x100);
+ out = 0x500;
+ result = base64_decode(tmp,&out,(const u8*)exhdrset->yaml->CommonHeaderKey.D,strlen(exhdrset->yaml->CommonHeaderKey.D));
+ if(result) goto finish;
+ memcpy(ncchset->CxiRsaKey.PrivK,tmp,0x100);
+ /* Set AccessDesc */
+ out = 0x500;
+ result = base64_decode(tmp,&out,(const u8*)exhdrset->yaml->AccessControlDescriptor.AccCtlDescSign,strlen(exhdrset->yaml->AccessControlDescriptor.AccCtlDescSign));
+ if(result) goto finish;
+ memcpy(exhdrset->ExHdr->AccessDescriptor.signature,tmp,0x100);
+ memcpy(exhdrset->ExHdr->AccessDescriptor.ncchpubkeymodulus,ncchset->CxiRsaKey.PubK,0x100);
+ out = 0x500;
+ result = base64_decode(tmp,&out,(const u8*)exhdrset->yaml->AccessControlDescriptor.AccCtlDescBin,strlen(exhdrset->yaml->AccessControlDescriptor.AccCtlDescBin));
+ if(result) goto finish;
+ memcpy(&exhdrset->ExHdr->AccessDescriptor.ARM11SystemLocalCapabilities,tmp,0x200);
+finish:
+ free(tmp);
+ return result;
+#endif
+ }
+ return 0;
+}
+
+/* ExHeader Binary Print Functions */
+void exhdr_Print_ServiceAccessControl(ExtendedHeader_Struct *hdr)
+{
+ printf("[+] Service Access Control\n");
+ for(int i = 0; i < 32; i ++){
+ char *SVC_Handle = (char*)hdr->ARM11SystemLocalCapabilities.ServiceAccessControl[i];
+ if(SVC_Handle[0] == 0) break;
+ printf("%.8s\n",hdr->ARM11SystemLocalCapabilities.ServiceAccessControl[i]);
+ }
+}
+
+/* ExHeader Binary Read Functions */
+u8* GetAccessDescSig_frm_exhdr(ExtendedHeader_Struct *hdr)
+{
+ if(!hdr) return NULL;
+ return hdr->AccessDescriptor.signature ;
+}
+
+u8* GetNcchHdrPubKey_frm_exhdr(ExtendedHeader_Struct *hdr)
+{
+ if(!hdr) return NULL;
+ return hdr->AccessDescriptor.ncchpubkeymodulus;
+}
+
+u8* GetAccessDesc_frm_exhdr(ExtendedHeader_Struct *hdr)
+{
+ if(!hdr) return NULL;
+ return hdr->AccessDescriptor.ncchpubkeymodulus;
+}
+
+u16 GetRemasterVersion_frm_exhdr(ExtendedHeader_Struct *hdr)
+{
+ return u8_to_u16(hdr->CodeSetInfo.Flags.remasterVersion,LE);
+}
+
+u64 GetSaveDataSize_frm_exhdr(ExtendedHeader_Struct *hdr)
+{
+ return u8_to_u64(hdr->SystemInfo.SaveDataSize,LE);
+}
+
+int GetCoreVersion_frm_exhdr(u8 *Dest, ExtendedHeader_Struct *hdr)
+{
+ return (int) memcpy(Dest,hdr->ARM11SystemLocalCapabilities.Flags,4);
+}
+
+int GetDependancyList_frm_exhdr(u8 *Dest,ExtendedHeader_Struct *hdr)
+{
+ if(!Dest) return -1;
+ for(int i = 0; i < 0x30; i++){
+ memcpy(Dest,hdr->DependencyList,0x30*8);
+ }
+ return 0;
+}
+
+/* ExHeader Settings Read from Yaml */
+int GetSaveDataSize_yaml(u64 *SaveDataSize, user_settings *usrset)
+{
+
+ if(usrset->yaml_set.DefaultSpec.Rom.SaveDataSize){
+ *SaveDataSize = strtoull(usrset->yaml_set.DefaultSpec.Rom.SaveDataSize,NULL,10);
+ if(strstr(usrset->yaml_set.DefaultSpec.Rom.SaveDataSize,"K")){
+ char *str = strstr(usrset->yaml_set.DefaultSpec.Rom.SaveDataSize,"K");
+ if(strcmp(str,"K") == 0 || strcmp(str,"KB") == 0 ){
+ *SaveDataSize = *SaveDataSize*KB;
+ }
+ }
+ else if(strstr(usrset->yaml_set.DefaultSpec.Rom.SaveDataSize,"M")){
+ char *str = strstr(usrset->yaml_set.DefaultSpec.Rom.SaveDataSize,"M");
+ if(strcmp(str,"M") == 0 || strcmp(str,"MB") == 0 ){
+ *SaveDataSize = *SaveDataSize*MB;
+ }
+ }
+ else if(strstr(usrset->yaml_set.DefaultSpec.Rom.SaveDataSize,"G")){
+ char *str = strstr(usrset->yaml_set.DefaultSpec.Rom.SaveDataSize,"G");
+ if(strcmp(str,"G") == 0 || strcmp(str,"GB") == 0 ){
+ *SaveDataSize = *SaveDataSize*GB;
+ }
+ }
+ else{
+ fprintf(stderr,"[EXHEADER ERROR] Invalid save data size format.\n");
+ return EXHDR_BAD_YAML_OPT;
+ }
+ if((*SaveDataSize & 65536) != 0){
+ fprintf(stderr,"[EXHEADER ERROR] Save data size must be aligned to 64K.\n");
+ return EXHDR_BAD_YAML_OPT;
+ }
+ }
+ else{
+ *SaveDataSize = 0;
+ }
+ return 0;
+}
+
+int GetRemasterVersion_yaml(u16 *RemasterVersion, user_settings *usrset)
+{
+ char *Str = usrset->yaml_set.DefaultSpec.SystemControlInfo.RemasterVersion;
+ if(!Str){
+ *RemasterVersion = 0;
+ return 0;
+ }
+ *RemasterVersion = strtol(Str,NULL,0);
+ return 0;
+}
\ No newline at end of file
diff --git a/exheader.h b/exheader.h
new file mode 100644
index 0000000..b2ebe83
--- /dev/null
+++ b/exheader.h
@@ -0,0 +1,188 @@
+#ifndef _EXHEADER_H_
+#define _EXHEADER_H_
+
+typedef enum
+{
+ COMMON_HEADER_KEY_NOT_FOUND = -10,
+ EXHDR_BAD_YAML_OPT = -11,
+} exheader_errors;
+
+typedef enum
+{
+ ExeFsCodeCompress = 1,
+ RetailSDAppFlag = 2,
+} SystemInfoFlags_Flagbitmask;
+
+typedef enum
+{
+ APPLICATION = 1,
+ SYSTEM = 2,
+ BASE = 3
+} MemoryTypeName;
+
+typedef enum
+{
+ PERMIT_DEBUG = 1,
+ FORCE_DEBUG = 2,
+ CAN_USE_NON_ALPHABET_AND_NUMBER = 4,
+ CAN_WRITE_SHARED_PAGE = 8,
+ CAN_USE_PRIVILEGE_PRIORITY = 16,
+ PERMIT_MAIN_FUNCTION_ARGUMENT = 32,
+ CAN_SHARE_DEVICE_MEMORY = 64,
+ RUNNABLE_ON_SLEEP = 128,
+ SPECIAL_MEMORY_ARRANGE = 4096
+} OtherCapabilities_Flagbitmask;
+
+typedef struct
+{
+ u8 reserved[5];
+ u8 flag;
+ u8 remasterVersion[2]; // le u16
+} exhdr_SystemInfoFlags;
+
+typedef struct
+{
+ u8 Address[4]; // le u32
+ u8 NumMaxPages[4]; // le u32
+ u8 CodeSize[4]; // le u32
+} exhdr_CodeSegmentInfo;
+
+typedef struct
+{
+ u8 Name[8];
+ exhdr_SystemInfoFlags Flags;
+ exhdr_CodeSegmentInfo TextSectionInfo;
+ u8 StackSize[4]; // le u32
+ exhdr_CodeSegmentInfo ReadOnlySectionInfo;
+ u8 Reserved[4];
+ exhdr_CodeSegmentInfo DataSectionInfo;
+ u8 BssSize[4]; // le u32
+} exhdr_CodeSetInfo;
+
+typedef struct
+{
+ u8 SaveDataSize[8];
+ u8 JumpId[8];
+ u8 Reserved[0x30];
+} exhdr_SystemInfo;
+
+typedef struct
+{
+ u8 extsavedataid[8];
+ u8 systemsavedataid[8];
+ u8 reserved[8];
+ u8 accessinfo[7];
+ u8 otherattributes;
+} exhdr_StorageInfo;
+
+typedef struct
+{
+ u8 ProgramId[8];
+ u8 Flags[8];
+ u8 MaxCpu;
+ u8 Reserved0;
+ u8 ResourceLimitDescriptor[15][2];
+ exhdr_StorageInfo StorageInfo;
+ u8 ServiceAccessControl[32][8]; // Those char[8] svc handles
+ u8 Reserved1[0x1f];
+ u8 ResourceLimitCategory;
+} exhdr_ARM11SystemLocalCapabilities;
+
+typedef struct
+{
+ u8 descriptors[28][4];// Descripters are a collection of u32s, with bitmask idents so they can be identified, no matter the pos
+ /*
+ struct
+ {
+ u32 data[8];
+ } SystemCallAccessControl;
+
+ struct
+ {
+ u32 data[8];
+ } InterruptNumberList;
+
+ struct
+ {
+
+ } AddressMapping;
+
+ struct
+ {
+ u32 Data; // le u32 : Flags
+ } OtherCapabilities;
+
+ struct
+ {
+ u32 Data;
+ } HandleTableSize;
+
+ struct
+ {
+ u32 Data;
+ } ReleaseKernelVersion;
+ */
+ u8 reserved[0x10];
+} exhdr_ARM11KernelCapabilities;
+
+typedef struct
+{
+ u8 descriptors[15];
+ u8 descversion;
+} exhdr_ARM9AccessControlInfo;
+
+typedef struct
+{
+ // systemcontrol info {
+ // coreinfo {
+ exhdr_CodeSetInfo CodeSetInfo;
+ u8 DependencyList[0x30][8];
+ // }
+ exhdr_SystemInfo SystemInfo;
+ // }
+ // accesscontrolinfo {
+ exhdr_ARM11SystemLocalCapabilities ARM11SystemLocalCapabilities;
+ exhdr_ARM11KernelCapabilities ARM11KernelCapabilities;
+ exhdr_ARM9AccessControlInfo ARM9AccessControlInfo;
+ // }
+ struct {
+ u8 signature[0x100];
+ u8 ncchpubkeymodulus[0x100];
+ exhdr_ARM11SystemLocalCapabilities ARM11SystemLocalCapabilities;
+ exhdr_ARM11KernelCapabilities ARM11KernelCapabilities;
+ exhdr_ARM9AccessControlInfo ARM9AccessControlInfo;
+ } AccessDescriptor;
+} ExtendedHeader_Struct;
+
+typedef struct
+{
+ keys_struct *keys;
+ desc_settings *yaml;
+
+ /* Output */
+ ExtendedHeader_Struct *ExHdr; // is the exheader output buffer ptr(in ncchset) cast as exheader struct ptr;
+} exheader_settings;
+
+#endif
+/* ExHeader Signature Functions */
+int SignAccessDesc(ExtendedHeader_Struct *ExHdr, keys_struct *keys);
+int CheckAccessDescSignature(ExtendedHeader_Struct *ExHdr, keys_struct *keys);
+
+/* ExHeader Build Functions */
+int BuildExHeader(ncch_settings *ncchset);
+
+/* ExHeader Binary Print Functions */
+void exhdr_Print_ServiceAccessControl(ExtendedHeader_Struct *hdr);
+
+/* ExHeader Binary Read Functions */
+u8* GetAccessDescSig_frm_exhdr(ExtendedHeader_Struct *hdr);
+u8* GetNcchHdrPubKey_frm_exhdr(ExtendedHeader_Struct *hdr);
+u8* GetAccessDesc_frm_exhdr(ExtendedHeader_Struct *hdr);
+u16 GetRemasterVersion_frm_exhdr(ExtendedHeader_Struct *hdr);
+u64 GetSaveDataSize_frm_exhdr(ExtendedHeader_Struct *hdr);
+int GetDependancyList_frm_exhdr(u8 *Dest,ExtendedHeader_Struct *hdr);
+int GetCoreVersion_frm_exhdr(u8 *Dest, ExtendedHeader_Struct *hdr);
+
+/* ExHeader Settings Read from Yaml */
+int GetSaveDataSize_yaml(u64 *SaveDataSize, user_settings *usrset);
+int GetRemasterVersion_yaml(u16 *RemasterVersion, user_settings *usrset);
\ No newline at end of file
diff --git a/keys_debug.h b/keys_debug.h
new file mode 100644
index 0000000..224290a
--- /dev/null
+++ b/keys_debug.h
@@ -0,0 +1,884 @@
+#ifndef _KEYS_DEBUG_H_
+#define _KEYS_DEBUG_H_
+
+// AES KEYS
+static const unsigned char zeros_fixed_aesKey[16] = //zeros_fixed_aesKey
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char system_fixed_aesKey[16] = //system_fixed_aesKey
+{
+ 0x52, 0x7C, 0xE6, 0x30, 0xA9, 0xCA, 0x30, 0x5F,
+ 0x36, 0x96, 0xF3, 0xCD, 0xE9, 0x54, 0x19, 0x4B
+};
+
+static const unsigned char ctr_aes_common_key_dev0[16] = //ctr_aes_common_key_dev0
+{
+ 0x55, 0xA3, 0xF8, 0x72, 0xBD, 0xC8, 0x0C, 0x55,
+ 0x5A, 0x65, 0x43, 0x81, 0x13, 0x9E, 0x15, 0x3B
+};
+
+static const unsigned char ctr_aes_common_key_dev1[16] = //ctr_aes_common_key_dev1
+{
+ 0x44, 0x34, 0xED, 0x14, 0x82, 0x0C, 0xA1, 0xEB,
+ 0xAB, 0x82, 0xC1, 0x6E, 0x7B, 0xEF, 0x0C, 0x25
+};
+
+static const unsigned char common_dpki_aesKey[16] = //common_dpki_aesKey
+{
+ 0xA1, 0x60, 0x4A, 0x6A, 0x71, 0x23, 0xB5, 0x29,
+ 0xAE, 0x8B, 0xEC, 0x32, 0xC8, 0x16, 0xFC, 0xAA
+};
+
+//ECC Keys
+
+static const unsigned char xs_dpki_eccPubKey[60] = //xs_dpki_eccPubKey
+{
+ 0x01, 0xD5, 0xA2, 0x3C, 0xE8, 0xE9, 0xDF, 0x8C,
+ 0x0A, 0xA5, 0xAA, 0xE1, 0x76, 0xE1, 0x24, 0x7C,
+ 0x90, 0x97, 0xA6, 0xFE, 0x2A, 0xD3, 0x8C, 0xB4,
+ 0xDE, 0x74, 0x32, 0xDE, 0x5B, 0x84, 0x01, 0xAC,
+ 0xB2, 0x13, 0x71, 0x9D, 0x4B, 0x9C, 0xEB, 0xD4,
+ 0x13, 0xC2, 0x27, 0x66, 0xC5, 0x5F, 0x83, 0x97,
+ 0xC4, 0x83, 0xA3, 0x9E, 0x3B, 0xFC, 0xE8, 0xA9,
+ 0xB5, 0x10, 0x3A, 0x7B
+};
+
+//RSA Keys
+
+static const unsigned char cert_root_rsa_pubk[0x200] =
+{
+ 0xD0, 0x1F, 0xE1, 0x00, 0xD4, 0x35, 0x56, 0xB2,
+ 0x4B, 0x56, 0xDA, 0xE9, 0x71, 0xB5, 0xA5, 0xD3,
+ 0x84, 0xB9, 0x30, 0x03, 0xBE, 0x1B, 0xBF, 0x28,
+ 0xA2, 0x30, 0x5B, 0x06, 0x06, 0x45, 0x46, 0x7D,
+ 0x5B, 0x02, 0x51, 0xD2, 0x56, 0x1A, 0x27, 0x4F,
+ 0x9E, 0x9F, 0x9C, 0xEC, 0x64, 0x61, 0x50, 0xAB,
+ 0x3D, 0x2A, 0xE3, 0x36, 0x68, 0x66, 0xAC, 0xA4,
+ 0xBA, 0xE8, 0x1A, 0xE3, 0xD7, 0x9A, 0xA6, 0xB0,
+ 0x4A, 0x8B, 0xCB, 0xA7, 0xE6, 0xFB, 0x64, 0x89,
+ 0x45, 0xEB, 0xDF, 0xDB, 0x85, 0xBA, 0x09, 0x1F,
+ 0xD7, 0xD1, 0x14, 0xB5, 0xA3, 0xA7, 0x80, 0xE3,
+ 0xA2, 0x2E, 0x6E, 0xCD, 0x87, 0xB5, 0xA4, 0xC6,
+ 0xF9, 0x10, 0xE4, 0x03, 0x22, 0x08, 0x81, 0x4B,
+ 0x0C, 0xEE, 0xA1, 0xA1, 0x7D, 0xF7, 0x39, 0x69,
+ 0x5F, 0x61, 0x7E, 0xF6, 0x35, 0x28, 0xDB, 0x94,
+ 0x96, 0x37, 0xA0, 0x56, 0x03, 0x7F, 0x7B, 0x32,
+ 0x41, 0x38, 0x95, 0xC0, 0xA8, 0xF1, 0x98, 0x2E,
+ 0x15, 0x65, 0xE3, 0x8E, 0xED, 0xC2, 0x2E, 0x59,
+ 0x0E, 0xE2, 0x67, 0x7B, 0x86, 0x09, 0xF4, 0x8C,
+ 0x2E, 0x30, 0x3F, 0xBC, 0x40, 0x5C, 0xAC, 0x18,
+ 0x04, 0x2F, 0x82, 0x20, 0x84, 0xE4, 0x93, 0x68,
+ 0x03, 0xDA, 0x7F, 0x41, 0x34, 0x92, 0x48, 0x56,
+ 0x2B, 0x8E, 0xE1, 0x2F, 0x78, 0xF8, 0x03, 0x24,
+ 0x63, 0x30, 0xBC, 0x7B, 0xE7, 0xEE, 0x72, 0x4A,
+ 0xF4, 0x58, 0xA4, 0x72, 0xE7, 0xAB, 0x46, 0xA1,
+ 0xA7, 0xC1, 0x0C, 0x2F, 0x18, 0xFA, 0x07, 0xC3,
+ 0xDD, 0xD8, 0x98, 0x06, 0xA1, 0x1C, 0x9C, 0xC1,
+ 0x30, 0xB2, 0x47, 0xA3, 0x3C, 0x8D, 0x47, 0xDE,
+ 0x67, 0xF2, 0x9E, 0x55, 0x77, 0xB1, 0x1C, 0x43,
+ 0x49, 0x3D, 0x5B, 0xBA, 0x76, 0x34, 0xA7, 0xE4,
+ 0xE7, 0x15, 0x31, 0xB7, 0xDF, 0x59, 0x81, 0xFE,
+ 0x24, 0xA1, 0x14, 0x55, 0x4C, 0xBD, 0x8F, 0x00,
+ 0x5C, 0xE1, 0xDB, 0x35, 0x08, 0x5C, 0xCF, 0xC7,
+ 0x78, 0x06, 0xB6, 0xDE, 0x25, 0x40, 0x68, 0xA2,
+ 0x6C, 0xB5, 0x49, 0x2D, 0x45, 0x80, 0x43, 0x8F,
+ 0xE1, 0xE5, 0xA9, 0xED, 0x75, 0xC5, 0xED, 0x45,
+ 0x1D, 0xCE, 0x78, 0x94, 0x39, 0xCC, 0xC3, 0xBA,
+ 0x28, 0xA2, 0x31, 0x2A, 0x1B, 0x87, 0x19, 0xEF,
+ 0x0F, 0x73, 0xB7, 0x13, 0x95, 0x0C, 0x02, 0x59,
+ 0x1A, 0x74, 0x62, 0xA6, 0x07, 0xF3, 0x7C, 0x0A,
+ 0xA7, 0xA1, 0x8F, 0xA9, 0x43, 0xA3, 0x6D, 0x75,
+ 0x2A, 0x5F, 0x41, 0x92, 0xF0, 0x13, 0x61, 0x00,
+ 0xAA, 0x9C, 0xB4, 0x1B, 0xBE, 0x14, 0xBE, 0xB1,
+ 0xF9, 0xFC, 0x69, 0x2F, 0xDF, 0xA0, 0x94, 0x46,
+ 0xDE, 0x5A, 0x9D, 0xDE, 0x2C, 0xA5, 0xF6, 0x8C,
+ 0x1C, 0x0C, 0x21, 0x42, 0x92, 0x87, 0xCB, 0x2D,
+ 0xAA, 0xA3, 0xD2, 0x63, 0x75, 0x2F, 0x73, 0xE0,
+ 0x9F, 0xAF, 0x44, 0x79, 0xD2, 0x81, 0x74, 0x29,
+ 0xF6, 0x98, 0x00, 0xAF, 0xDE, 0x6B, 0x59, 0x2D,
+ 0xC1, 0x98, 0x82, 0xBD, 0xF5, 0x81, 0xCC, 0xAB,
+ 0xF2, 0xCB, 0x91, 0x02, 0x9E, 0xF3, 0x5C, 0x4C,
+ 0xFD, 0xBB, 0xFF, 0x49, 0xC1, 0xFA, 0x1B, 0x2F,
+ 0xE3, 0x1D, 0xE7, 0xA5, 0x60, 0xEC, 0xB4, 0x7E,
+ 0xBC, 0xFE, 0x32, 0x42, 0x5B, 0x95, 0x6F, 0x81,
+ 0xB6, 0x99, 0x17, 0x48, 0x7E, 0x3B, 0x78, 0x91,
+ 0x51, 0xDB, 0x2E, 0x78, 0xB1, 0xFD, 0x2E, 0xBE,
+ 0x7E, 0x62, 0x6B, 0x3E, 0xA1, 0x65, 0xB4, 0xFB,
+ 0x00, 0xCC, 0xB7, 0x51, 0xAF, 0x50, 0x73, 0x29,
+ 0xC4, 0xA3, 0x93, 0x9E, 0xA6, 0xDD, 0x9C, 0x50,
+ 0xA0, 0xE7, 0x38, 0x6B, 0x01, 0x45, 0x79, 0x6B,
+ 0x41, 0xAF, 0x61, 0xF7, 0x85, 0x55, 0x94, 0x4F,
+ 0x3B, 0xC2, 0x2D, 0xC3, 0xBD, 0x0D, 0x00, 0xF8,
+ 0x79, 0x8A, 0x42, 0xB1, 0xAA, 0xA0, 0x83, 0x20,
+ 0x65, 0x9A, 0xC7, 0x39, 0x5A, 0xB4, 0xF3, 0x29
+};
+
+static const unsigned char cpA_dpki_rsa_privExp[256] = //cpA_dpki_rsa_privExp
+{
+ 0x28, 0xCE, 0xDC, 0x39, 0x02, 0x7F, 0x3E, 0x8E,
+ 0xAA, 0xB7, 0x59, 0x11, 0xE0, 0x68, 0xBF, 0x80,
+ 0xA6, 0x44, 0x77, 0xDB, 0x1B, 0xA2, 0x50, 0xA3,
+ 0x69, 0xE5, 0x96, 0xB2, 0xC4, 0xCA, 0x7A, 0x35,
+ 0x0D, 0xFC, 0x4A, 0xB2, 0xFB, 0xC0, 0x18, 0xA5,
+ 0x30, 0xB4, 0x9D, 0x10, 0x44, 0xD1, 0xAD, 0x33,
+ 0xFD, 0x15, 0xA7, 0x8D, 0x0F, 0x17, 0xD5, 0xA4,
+ 0xF5, 0x5E, 0x7F, 0x33, 0xF6, 0x80, 0x04, 0x27,
+ 0x6A, 0xEA, 0x9C, 0xEE, 0x68, 0x04, 0x1A, 0xA5,
+ 0xD4, 0x35, 0xA2, 0x25, 0xA2, 0x31, 0xD9, 0xF2,
+ 0xF0, 0xAC, 0xDE, 0x69, 0xB6, 0x64, 0x56, 0x75,
+ 0x2E, 0x9B, 0xEA, 0xDE, 0x2A, 0xBB, 0xD6, 0x00,
+ 0xAA, 0xE6, 0x9B, 0xC2, 0xF6, 0x9F, 0x60, 0xCD,
+ 0x0E, 0xFA, 0xB1, 0x14, 0x4A, 0x47, 0xD6, 0x63,
+ 0x9A, 0xCD, 0x9C, 0x93, 0xB9, 0x09, 0x42, 0xDA,
+ 0x8F, 0xFB, 0xE5, 0x7B, 0xF1, 0x4F, 0x96, 0x33,
+ 0xF9, 0x45, 0x5B, 0xCC, 0x84, 0xAB, 0xC2, 0xD8,
+ 0xC4, 0x0C, 0x85, 0xFA, 0x51, 0x28, 0xB9, 0x97,
+ 0x95, 0x23, 0x8C, 0xB3, 0x1D, 0x4E, 0xB6, 0x1C,
+ 0xCC, 0x60, 0x41, 0xFB, 0x26, 0xC7, 0xD6, 0xCB,
+ 0x77, 0x18, 0xF7, 0xEA, 0xCD, 0x10, 0x3C, 0x5B,
+ 0xA3, 0xC0, 0x77, 0x4C, 0x11, 0xF3, 0x74, 0x50,
+ 0xEE, 0x23, 0x80, 0xC4, 0x5D, 0xDD, 0x57, 0xF5,
+ 0x7D, 0x49, 0x57, 0x4A, 0xBA, 0x62, 0xBF, 0x06,
+ 0xD9, 0xD1, 0x7F, 0x91, 0x10, 0x89, 0x6F, 0x49,
+ 0x09, 0xD7, 0xE9, 0xAF, 0x4C, 0x9F, 0x67, 0x9D,
+ 0x89, 0x82, 0xE4, 0xD5, 0xC1, 0x9A, 0xDC, 0x55,
+ 0x79, 0xE7, 0xE9, 0x2D, 0x81, 0x42, 0x14, 0x55,
+ 0x61, 0x47, 0x9B, 0xED, 0x76, 0x92, 0x1D, 0x2F,
+ 0xB5, 0x7C, 0x28, 0x4B, 0xFF, 0x7B, 0xC2, 0x3B,
+ 0x36, 0x73, 0x99, 0xA6, 0x21, 0x43, 0x0E, 0xA1,
+ 0x1F, 0x82, 0xB8, 0x91, 0x71, 0x11, 0xB2, 0xC1
+};
+
+static const unsigned char cpA_dpki_rsa_pubMod[256] = //cpA_dpki_rsa_pubMod
+{
+ 0xAA, 0x7F, 0x93, 0x80, 0x28, 0x9B, 0xE8, 0x98,
+ 0x63, 0x10, 0x7A, 0xE1, 0x0C, 0x59, 0x2C, 0x2F,
+ 0x7C, 0xFF, 0xBD, 0xAA, 0xDD, 0x74, 0xF4, 0xA2,
+ 0xFB, 0xAC, 0xD7, 0x6F, 0x00, 0x93, 0x42, 0x06,
+ 0x34, 0x71, 0x56, 0xD8, 0x40, 0x49, 0x72, 0x9F,
+ 0x3E, 0x24, 0xFA, 0x5E, 0x19, 0xD1, 0x5B, 0x63,
+ 0x5C, 0xD2, 0xEF, 0x09, 0xDE, 0x32, 0xEE, 0x6B,
+ 0x6F, 0xC8, 0xFA, 0x32, 0x8E, 0x2E, 0x96, 0xB9,
+ 0x94, 0x41, 0x04, 0x7D, 0x07, 0x62, 0x95, 0xDA,
+ 0x0D, 0x91, 0xD8, 0x09, 0x35, 0xD0, 0xDE, 0x8E,
+ 0x6B, 0xC6, 0xAB, 0x14, 0x27, 0x01, 0x9C, 0xFE,
+ 0x49, 0x96, 0xFC, 0x9B, 0x54, 0x79, 0x4D, 0xEB,
+ 0xD7, 0xC6, 0x66, 0x73, 0xA6, 0xDD, 0x3A, 0x77,
+ 0x65, 0x47, 0x94, 0xEC, 0x1C, 0x87, 0xAA, 0x46,
+ 0xD9, 0x78, 0xA9, 0x7D, 0xDB, 0x11, 0x22, 0x6E,
+ 0xD4, 0x12, 0xC2, 0x78, 0x4B, 0x21, 0x83, 0x92,
+ 0xC7, 0x10, 0xC7, 0x74, 0x19, 0xFF, 0xAA, 0xF6,
+ 0x0B, 0x75, 0xD8, 0x23, 0xDD, 0x33, 0xC3, 0xA1,
+ 0x5B, 0xA7, 0x2D, 0x30, 0xA5, 0xA4, 0xD8, 0xF8,
+ 0x0F, 0xD6, 0x73, 0xFD, 0x26, 0xCB, 0x29, 0xA6,
+ 0xEF, 0x50, 0x39, 0xE2, 0x5F, 0x59, 0x61, 0x84,
+ 0x6B, 0xDA, 0x2E, 0xC7, 0xCB, 0xE4, 0x38, 0x4B,
+ 0x28, 0xFB, 0x0D, 0xD5, 0x8E, 0x7C, 0xAA, 0x7D,
+ 0x4B, 0x37, 0x3A, 0xD7, 0x81, 0xDD, 0x73, 0xE3,
+ 0x09, 0x93, 0xBD, 0xBD, 0x7E, 0x08, 0x55, 0x4A,
+ 0x8C, 0xA5, 0xC9, 0x84, 0x2D, 0x71, 0x01, 0xA2,
+ 0x2A, 0x01, 0xB0, 0x15, 0xFB, 0x30, 0x78, 0xB9,
+ 0x13, 0xF4, 0xC7, 0x3F, 0xB5, 0xA6, 0xF1, 0xA2,
+ 0x5E, 0x22, 0xB0, 0x02, 0xB6, 0xE0, 0x09, 0x54,
+ 0x7F, 0x0F, 0xBD, 0xF0, 0xFE, 0xA5, 0x50, 0x1D,
+ 0x93, 0x15, 0xF9, 0x3D, 0x83, 0x0F, 0x0F, 0x0E,
+ 0x3D, 0xE2, 0x3D, 0x96, 0xE7, 0x09, 0xD9, 0x77
+};
+
+static const unsigned char xs9_dpki_rsa_privExp[256] = //xs9_dpki_rsa_privExp
+{
+ 0x74, 0xCB, 0xCF, 0x1E, 0xD0, 0x2D, 0xD4, 0xF9,
+ 0xE0, 0x05, 0xCE, 0x9C, 0x66, 0x3D, 0xE3, 0x62,
+ 0x66, 0x62, 0x4E, 0xB5, 0x82, 0xE1, 0x24, 0x1B,
+ 0x5F, 0x73, 0x2A, 0x7F, 0x1D, 0xB3, 0x6E, 0x50,
+ 0x07, 0x83, 0xA0, 0xC0, 0xED, 0xCE, 0xB7, 0xF9,
+ 0x3D, 0xAC, 0x61, 0xC5, 0x7B, 0x99, 0xA0, 0xBC,
+ 0xCE, 0x42, 0x8F, 0xD3, 0xB0, 0xA5, 0xBF, 0x2A,
+ 0x3D, 0x3E, 0x5E, 0xDC, 0x56, 0xC3, 0xA5, 0xDE,
+ 0x35, 0xCD, 0x0A, 0x00, 0xF8, 0x17, 0x6B, 0x20,
+ 0x79, 0xEF, 0xD8, 0x83, 0x23, 0xBF, 0x21, 0x28,
+ 0xFF, 0x38, 0x7D, 0x80, 0x07, 0x15, 0x18, 0x6C,
+ 0xB9, 0x20, 0xF8, 0x85, 0x77, 0xBC, 0xD9, 0x2A,
+ 0x35, 0x1C, 0xFE, 0xE3, 0xF1, 0xE8, 0x98, 0x2E,
+ 0xA0, 0x4A, 0x48, 0x77, 0x35, 0x03, 0xC9, 0x7A,
+ 0xAC, 0xDA, 0xBE, 0x6D, 0x1D, 0xFB, 0xE4, 0xDE,
+ 0xEC, 0x70, 0x65, 0xFA, 0x10, 0x65, 0xA4, 0xB8,
+ 0x6A, 0xDF, 0x32, 0x6B, 0x8E, 0x28, 0x79, 0x25,
+ 0x87, 0x72, 0xC0, 0x7C, 0x5B, 0x81, 0xBC, 0x81,
+ 0x92, 0x44, 0x7D, 0xEA, 0x61, 0xBD, 0x3C, 0x48,
+ 0xF3, 0x0E, 0x18, 0xDC, 0x8D, 0x89, 0xA0, 0x34,
+ 0xC3, 0xAE, 0x9C, 0x57, 0x72, 0xA6, 0xD7, 0x7C,
+ 0x79, 0xF7, 0xE9, 0x14, 0x6E, 0x15, 0xAC, 0x01,
+ 0xFA, 0xFF, 0xC8, 0xA2, 0x2A, 0x3A, 0xAB, 0x24,
+ 0x3C, 0x7E, 0x2E, 0xC5, 0xDA, 0x83, 0xD5, 0x9D,
+ 0x24, 0x10, 0x83, 0x7A, 0xF4, 0xBB, 0xA3, 0x6F,
+ 0x88, 0xCE, 0xEC, 0x24, 0x1B, 0xF4, 0x36, 0x2E,
+ 0x96, 0xC9, 0x6D, 0x19, 0x02, 0xFE, 0xAA, 0x21,
+ 0x3E, 0x95, 0xA7, 0xFE, 0x83, 0xC8, 0x99, 0x7F,
+ 0xD1, 0xCB, 0x7C, 0x1F, 0x91, 0x30, 0xDB, 0xA4,
+ 0xD3, 0xDD, 0xDA, 0x9B, 0x12, 0x4E, 0x24, 0xD1,
+ 0xA5, 0x6F, 0x15, 0xFC, 0x2C, 0x72, 0x98, 0x2C,
+ 0x89, 0xC5, 0x7D, 0x89, 0xDE, 0x2B, 0x4E, 0x01
+};
+
+static const unsigned char xs9_dpki_rsa_pubMod[256] = //xs9_dpki_rsa_pubMod
+{
+ 0xC0, 0x84, 0x4C, 0xEB, 0x7E, 0xB0, 0xCF, 0xF0,
+ 0xAE, 0xB7, 0x77, 0x69, 0x85, 0x93, 0xE4, 0x99,
+ 0x5A, 0x95, 0x4E, 0x58, 0x17, 0x38, 0xCE, 0xD6,
+ 0x81, 0xB0, 0xBD, 0x77, 0x09, 0xE7, 0xF8, 0x9A,
+ 0xDF, 0xAD, 0x05, 0x48, 0x83, 0xF6, 0xC3, 0xFD,
+ 0xDF, 0x7B, 0x83, 0xE0, 0x0C, 0x26, 0x81, 0x54,
+ 0x43, 0x29, 0xEA, 0x82, 0x6C, 0x89, 0xF0, 0xA6,
+ 0x74, 0x42, 0x86, 0x4D, 0x32, 0x60, 0x32, 0x7D,
+ 0xA7, 0x7A, 0x13, 0x40, 0x66, 0x59, 0xDA, 0x3E,
+ 0x41, 0x6B, 0x27, 0x94, 0x03, 0x4F, 0xAA, 0x22,
+ 0x9D, 0xD5, 0x54, 0x52, 0xDB, 0x27, 0x0A, 0x6A,
+ 0xA2, 0x3D, 0x19, 0xB1, 0x66, 0x1B, 0x19, 0x7D,
+ 0xAB, 0xC7, 0x0E, 0x88, 0x17, 0x91, 0xA1, 0x2A,
+ 0xB4, 0x3C, 0x6C, 0xCB, 0xF5, 0xAA, 0x7C, 0x3A,
+ 0xDD, 0x36, 0xFB, 0x35, 0x71, 0x7B, 0x20, 0x01,
+ 0x59, 0x00, 0xD6, 0xF6, 0x90, 0x39, 0x35, 0x41,
+ 0x31, 0xF8, 0xC1, 0xC0, 0x57, 0x3A, 0x35, 0x18,
+ 0x58, 0x90, 0xB1, 0xAD, 0x9A, 0x0E, 0xEC, 0xE0,
+ 0xF4, 0x7A, 0x7D, 0xA5, 0x27, 0x48, 0xC9, 0x72,
+ 0xAB, 0x0D, 0x08, 0x7B, 0x62, 0x35, 0x40, 0x91,
+ 0x14, 0x2B, 0xB1, 0x1D, 0x1A, 0xFA, 0xF9, 0xCD,
+ 0x5C, 0x17, 0x13, 0x53, 0x52, 0x71, 0xCA, 0xE2,
+ 0x2A, 0x78, 0xB1, 0x7F, 0x4A, 0xCD, 0x59, 0xD8,
+ 0xBA, 0x1D, 0x7D, 0x70, 0x5F, 0x78, 0x1B, 0x9F,
+ 0x9D, 0x37, 0x18, 0x8E, 0xD7, 0xCD, 0x0D, 0x49,
+ 0x57, 0x74, 0x69, 0x88, 0x3A, 0x6B, 0x8E, 0x4E,
+ 0x1B, 0x85, 0xDD, 0xBE, 0x39, 0x45, 0x05, 0x89,
+ 0x56, 0x12, 0x97, 0x59, 0x9A, 0x09, 0xA4, 0xC8,
+ 0x2D, 0x2F, 0xF5, 0xCF, 0xB4, 0x73, 0x70, 0xDB,
+ 0x58, 0x1E, 0xB2, 0x4E, 0x77, 0x6F, 0xA4, 0x7E,
+ 0x62, 0xDF, 0xB7, 0x05, 0xE8, 0x80, 0x42, 0x5C,
+ 0xB8, 0x78, 0x87, 0x97, 0x7F, 0x66, 0x2C, 0x5F
+};
+
+static const unsigned char DevNcsdCfa_privExp[256] = //DevNcsdCfa_privExp
+{
+ 0x32, 0x36, 0x43, 0xC2, 0xB3, 0x1A, 0x7E, 0x13,
+ 0xAB, 0xA2, 0xB6, 0x8B, 0x4F, 0x05, 0xA7, 0xA6,
+ 0xCD, 0xE7, 0xA6, 0x74, 0x47, 0x49, 0xE6, 0x51,
+ 0xE4, 0x71, 0x74, 0x15, 0x76, 0x91, 0xF7, 0x92,
+ 0xB1, 0x4E, 0xF6, 0x99, 0x73, 0x1E, 0xCF, 0xB5,
+ 0x1D, 0x7C, 0xAF, 0xC5, 0xEA, 0x57, 0x01, 0xE5,
+ 0x5C, 0x10, 0x47, 0xEA, 0x3A, 0x54, 0x86, 0x03,
+ 0x2A, 0x76, 0x05, 0x72, 0x53, 0x16, 0xC2, 0xAE,
+ 0x2D, 0xBE, 0x71, 0xF7, 0x17, 0x6B, 0x23, 0xDD,
+ 0x2C, 0xB8, 0x8D, 0x13, 0x14, 0xE5, 0xDA, 0x3B,
+ 0xC7, 0x33, 0x7A, 0xBA, 0xE5, 0x2A, 0x2B, 0x7D,
+ 0x5A, 0x12, 0x27, 0x38, 0x56, 0xDF, 0xED, 0x70,
+ 0x03, 0x0E, 0xED, 0x64, 0xC7, 0xF6, 0x54, 0xAC,
+ 0xFE, 0x1D, 0x77, 0xA4, 0xE4, 0xBC, 0xEB, 0xB9,
+ 0xA6, 0xC5, 0xFE, 0x3A, 0xAF, 0x58, 0x81, 0xE4,
+ 0x3F, 0xA0, 0xE6, 0x93, 0x13, 0x2D, 0x98, 0x7D,
+ 0xB3, 0xE2, 0xC9, 0xC8, 0xD6, 0x31, 0x91, 0x73,
+ 0x9D, 0xCA, 0xC9, 0x44, 0xEF, 0xD0, 0x39, 0xBF,
+ 0x38, 0xFD, 0x1C, 0x91, 0x72, 0x93, 0x40, 0xA9,
+ 0x8A, 0x0D, 0x3E, 0x32, 0xC4, 0x59, 0x4B, 0x0C,
+ 0xC7, 0xEA, 0x50, 0x41, 0x9F, 0xF5, 0xE2, 0xB7,
+ 0x50, 0x7C, 0xE3, 0xC9, 0xEC, 0x46, 0x18, 0xAC,
+ 0xB4, 0x91, 0x2A, 0x32, 0xE0, 0xD8, 0x10, 0x6F,
+ 0xFC, 0x81, 0xB3, 0x95, 0xF3, 0xFC, 0x78, 0xC0,
+ 0xEF, 0xE5, 0x7B, 0x8D, 0x14, 0xD4, 0x36, 0x26,
+ 0x5F, 0xC6, 0x32, 0xC0, 0x19, 0x87, 0x5C, 0x77,
+ 0x26, 0x37, 0xD8, 0xAE, 0x66, 0xD6, 0x0B, 0x28,
+ 0x26, 0x43, 0x7C, 0x25, 0xDB, 0x6D, 0x5C, 0xE8,
+ 0x94, 0x8F, 0xA9, 0x77, 0x07, 0xB2, 0xC0, 0x85,
+ 0xCD, 0x41, 0xBA, 0x48, 0x88, 0x73, 0x34, 0xD5,
+ 0x20, 0x8A, 0x0F, 0xE3, 0x9E, 0x99, 0xF0, 0xC8,
+ 0xE8, 0xD9, 0x2C, 0x2A, 0x21, 0x69, 0xE4, 0xC1
+};
+
+static const unsigned char DevNcsdCfa_pubMod[256] = //DevNcsdCfa_pubMod
+{
+ 0xB9, 0x0C, 0xC4, 0xC6, 0x78, 0xF8, 0x6E, 0x30,
+ 0x05, 0x28, 0xC1, 0xCB, 0xD2, 0xCF, 0xA7, 0x80,
+ 0x5C, 0x57, 0x4D, 0x16, 0x9C, 0xAF, 0xA6, 0xCD,
+ 0x01, 0xBB, 0x83, 0x33, 0xAD, 0x03, 0xBB, 0x06,
+ 0x63, 0xD8, 0x17, 0xF5, 0xE3, 0xDF, 0xDA, 0x0D,
+ 0x3B, 0x86, 0x0E, 0xA2, 0x80, 0x47, 0x94, 0x44,
+ 0x6F, 0xD9, 0x97, 0x7E, 0x78, 0x6A, 0xC3, 0x93,
+ 0x93, 0xEF, 0x02, 0xFC, 0x22, 0x9F, 0x80, 0x77,
+ 0x8C, 0x70, 0x92, 0x1C, 0x43, 0xB1, 0x37, 0x4C,
+ 0x76, 0xE0, 0x57, 0x3B, 0xAB, 0x89, 0xFF, 0xEF,
+ 0xE5, 0xBB, 0x3E, 0xAB, 0x91, 0x39, 0xB8, 0xD9,
+ 0x66, 0x0B, 0x64, 0x28, 0x91, 0x92, 0xE9, 0xD0,
+ 0xB3, 0xDF, 0xD1, 0x4B, 0xC1, 0x73, 0xB5, 0x3F,
+ 0x56, 0xA0, 0x40, 0x10, 0xFE, 0x15, 0x2B, 0x1F,
+ 0xA2, 0x7A, 0xDE, 0x31, 0xB0, 0x26, 0x40, 0xC3,
+ 0x57, 0xFD, 0x35, 0xCB, 0xF0, 0xFA, 0xFF, 0xFB,
+ 0x6F, 0xDB, 0xCD, 0x34, 0x1D, 0x51, 0x2D, 0x2D,
+ 0x81, 0x18, 0xFF, 0x0C, 0x08, 0x51, 0xD5, 0xB4,
+ 0x4B, 0x56, 0x16, 0x02, 0x9F, 0x4E, 0x6A, 0xDF,
+ 0x06, 0x6E, 0xCB, 0x72, 0x85, 0xE9, 0x2E, 0x43,
+ 0xA2, 0x08, 0x78, 0x0C, 0x38, 0x9C, 0x19, 0xBD,
+ 0x7B, 0x74, 0x74, 0x68, 0xC4, 0x2D, 0xC1, 0x35,
+ 0x9E, 0x65, 0x3B, 0xD8, 0x99, 0x04, 0x1C, 0x8B,
+ 0x93, 0x8E, 0x7E, 0x92, 0x7C, 0xBB, 0xDD, 0x60,
+ 0xEC, 0xE7, 0xFE, 0x0E, 0x9D, 0x4F, 0x36, 0x46,
+ 0xE6, 0xF1, 0x5C, 0x94, 0x70, 0xEE, 0x67, 0x5F,
+ 0x36, 0x2B, 0x70, 0x44, 0x8D, 0xCA, 0x09, 0xB9,
+ 0x58, 0x67, 0xD2, 0x9F, 0xAD, 0x1F, 0x13, 0x54,
+ 0x74, 0xAD, 0xA6, 0x84, 0x44, 0x28, 0xF3, 0xDE,
+ 0x7E, 0x4C, 0x20, 0x2B, 0xC5, 0xE9, 0x12, 0xE9,
+ 0x5E, 0xFB, 0x8D, 0x77, 0xA9, 0xA4, 0xD2, 0x0D,
+ 0x3C, 0x38, 0x24, 0xBE, 0xF5, 0x8A, 0xB5, 0xF5
+};
+
+static const unsigned char AccessDesc_privExp[256] = //AccessDesc_privExp
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char AccessDesc_pubMod[256] = //AccessDesc_pubMod
+{
+ 0xF4, 0x3C, 0x45, 0x82, 0xFB, 0xF8, 0x90, 0x5D,
+ 0x07, 0x02, 0x9F, 0x2A, 0x98, 0x8B, 0x63, 0xB7,
+ 0xD3, 0x8F, 0x3C, 0xE2, 0xE0, 0xE0, 0x93, 0xBF,
+ 0xDF, 0x32, 0x43, 0x4D, 0xBE, 0xF4, 0xD1, 0x7A,
+ 0x3A, 0x4E, 0x54, 0x31, 0xD7, 0x73, 0xAE, 0x99,
+ 0x4C, 0xC4, 0x1F, 0x3C, 0x3E, 0xF0, 0x57, 0x05,
+ 0xA3, 0x8A, 0x45, 0x54, 0x60, 0xD8, 0x8F, 0xD9,
+ 0x1D, 0x68, 0x0D, 0x0E, 0x2E, 0xEF, 0xC8, 0xE8,
+ 0x3D, 0xC9, 0x19, 0xF3, 0x73, 0x1E, 0x2D, 0xDA,
+ 0x77, 0x88, 0x3E, 0xCA, 0x5E, 0x25, 0x70, 0x4B,
+ 0xF7, 0x70, 0x95, 0x83, 0x54, 0x24, 0xE0, 0xC3,
+ 0x1A, 0x75, 0xDF, 0x61, 0x3D, 0xD1, 0x42, 0xEC,
+ 0x35, 0x1B, 0x38, 0xD6, 0xC1, 0xF6, 0x7E, 0x18,
+ 0x2A, 0x84, 0x85, 0xDD, 0x57, 0x74, 0x1F, 0x0A,
+ 0x2E, 0xF6, 0xB2, 0x94, 0xA2, 0x3E, 0xE9, 0xA1,
+ 0xD0, 0x09, 0xF7, 0x3A, 0x99, 0x80, 0x05, 0xAF,
+ 0x57, 0x55, 0xEF, 0x52, 0xFA, 0x24, 0x3E, 0x7F,
+ 0xD4, 0x7C, 0x41, 0x44, 0x7B, 0x06, 0x7F, 0xB9,
+ 0x5B, 0x2E, 0x8E, 0x96, 0xAE, 0x46, 0x12, 0x4D,
+ 0x64, 0x21, 0xE5, 0x0F, 0x85, 0xCC, 0xEB, 0x92,
+ 0xE5, 0xF0, 0xF5, 0xA7, 0x42, 0x27, 0x3B, 0xEC,
+ 0xF8, 0xE7, 0x81, 0x75, 0x6F, 0x63, 0x0A, 0x8B,
+ 0x0D, 0x77, 0x38, 0x51, 0xE6, 0x66, 0x33, 0xBA,
+ 0x79, 0xDC, 0x2F, 0x2C, 0x8F, 0xC3, 0x28, 0x06,
+ 0xBB, 0x03, 0x9C, 0xDB, 0xD1, 0x64, 0x0A, 0x66,
+ 0xF0, 0xF8, 0xC1, 0x2A, 0x49, 0x1D, 0x0C, 0x6E,
+ 0x35, 0xBB, 0xEA, 0xB3, 0x5C, 0x0D, 0xE9, 0x95,
+ 0x7C, 0x67, 0xBE, 0x65, 0x77, 0xEC, 0x07, 0xC0,
+ 0x23, 0x05, 0x0A, 0x72, 0x48, 0x86, 0xE9, 0x9E,
+ 0xFC, 0x25, 0x15, 0xE7, 0xC8, 0x21, 0x65, 0xE0,
+ 0x1B, 0xD5, 0xD5, 0x0E, 0xD3, 0x11, 0x54, 0xBB,
+ 0x29, 0x78, 0xBF, 0x2A, 0x3C, 0x3B, 0xB6, 0xB1
+};
+
+static const unsigned char CrrDevKey_privExp[256] = //CrrDevKey_privExp
+{
+ 0x8D, 0x27, 0x29, 0x6B, 0xC7, 0xA7, 0xED, 0xCD,
+ 0x94, 0x2D, 0x36, 0x5E, 0x86, 0xA8, 0x26, 0xE7,
+ 0x43, 0x9E, 0x64, 0xC8, 0xAA, 0x9A, 0x58, 0x21,
+ 0x07, 0xF7, 0xB3, 0xFB, 0xCF, 0x8D, 0x3E, 0x53,
+ 0xF0, 0x02, 0x25, 0x7B, 0x80, 0x18, 0x2E, 0x0D,
+ 0x84, 0x7D, 0x6C, 0xE0, 0xDA, 0xC0, 0x17, 0xA6,
+ 0xA5, 0x13, 0xE6, 0xFD, 0xBF, 0x98, 0xFC, 0x87,
+ 0x9A, 0x9E, 0x0E, 0x13, 0x87, 0x66, 0x24, 0x8D,
+ 0xA5, 0x6C, 0x58, 0x86, 0x10, 0x80, 0x90, 0x89,
+ 0xEE, 0xFD, 0x40, 0x94, 0xCB, 0x1F, 0x26, 0xAB,
+ 0xD1, 0xD3, 0xFF, 0xE9, 0x7B, 0x76, 0xDC, 0x65,
+ 0xC0, 0x15, 0xD8, 0x9B, 0xF6, 0x29, 0xE1, 0x49,
+ 0xE9, 0xDC, 0xBE, 0x24, 0x17, 0xFF, 0x09, 0x2C,
+ 0xD6, 0xC4, 0x6D, 0x50, 0x33, 0xDC, 0xA0, 0x9D,
+ 0x9D, 0xCC, 0xDD, 0x6E, 0x7B, 0xDF, 0x42, 0x22,
+ 0x4D, 0x80, 0xC7, 0xEB, 0xCB, 0xB1, 0x60, 0x2F,
+ 0x04, 0xEE, 0x04, 0x0E, 0x4C, 0x76, 0x49, 0x55,
+ 0x92, 0xA5, 0xC1, 0x13, 0x60, 0x0A, 0x80, 0x15,
+ 0x3D, 0x1C, 0xC6, 0x46, 0x57, 0x2E, 0x7C, 0xB0,
+ 0x3D, 0x87, 0x06, 0x87, 0xFD, 0x31, 0xF8, 0xE7,
+ 0x14, 0x97, 0x2A, 0x57, 0x40, 0xAC, 0x94, 0x61,
+ 0xCD, 0xCF, 0xDE, 0x8C, 0x40, 0x46, 0x95, 0xA0,
+ 0xD6, 0xF9, 0x2C, 0x08, 0x9B, 0x12, 0xBF, 0xF1,
+ 0x88, 0x9C, 0x5D, 0x40, 0x32, 0x6D, 0x9D, 0x99,
+ 0xA4, 0x80, 0xA6, 0xC2, 0x45, 0x5A, 0xD3, 0x22,
+ 0xFE, 0xFA, 0x17, 0x54, 0x11, 0xEA, 0x41, 0xB4,
+ 0xBD, 0x68, 0x1E, 0xDD, 0x3F, 0xE5, 0x92, 0xCB,
+ 0x9E, 0xF8, 0xC0, 0x0A, 0x8B, 0xF5, 0x89, 0xA4,
+ 0x03, 0x68, 0xF8, 0xF8, 0x99, 0x7C, 0xFE, 0xAD,
+ 0x32, 0xDD, 0x5C, 0xB4, 0x06, 0x29, 0xDA, 0x96,
+ 0x8B, 0xBA, 0xCB, 0x15, 0xDE, 0x38, 0x0D, 0xCA,
+ 0xF7, 0x01, 0x65, 0xF6, 0x2D, 0x36, 0x6E, 0x71
+};
+
+static const unsigned char CrrDevKey_pubMod[256] = //CrrDevKey_pubMod
+{
+ 0xE2, 0xAD, 0xA6, 0xEA, 0xCA, 0xA3, 0xE8, 0xCC,
+ 0xA9, 0x70, 0x1D, 0x2E, 0x23, 0x4B, 0xC6, 0x55,
+ 0xCE, 0x13, 0xD9, 0xA7, 0x58, 0xB4, 0xC7, 0x73,
+ 0x96, 0x1D, 0xE8, 0xC3, 0x09, 0x4D, 0x9B, 0xC3,
+ 0xEB, 0x69, 0xA2, 0x37, 0x83, 0x5D, 0xD8, 0x37,
+ 0x04, 0x72, 0x7A, 0x4F, 0xEA, 0x53, 0x98, 0x9D,
+ 0x0E, 0x01, 0x34, 0x70, 0x9A, 0x82, 0x06, 0xE7,
+ 0x6A, 0xC9, 0xF8, 0x0E, 0x49, 0x5A, 0xA4, 0xE7,
+ 0x0E, 0xFA, 0xD4, 0xAB, 0x3B, 0xC5, 0xD7, 0xF1,
+ 0xA4, 0xFC, 0x92, 0x7F, 0xD0, 0xF3, 0xCD, 0xD5,
+ 0xB9, 0x2A, 0x1A, 0x41, 0x62, 0xB3, 0x7B, 0x3E,
+ 0x1E, 0x35, 0x46, 0x41, 0x8E, 0xB2, 0x53, 0x1A,
+ 0x60, 0xF8, 0xC2, 0xD1, 0x94, 0xB3, 0x9D, 0x76,
+ 0x9F, 0x1D, 0x98, 0xAC, 0xF0, 0xCF, 0xE3, 0xA9,
+ 0x05, 0x85, 0xF2, 0xBF, 0x55, 0x76, 0x1B, 0x89,
+ 0x1C, 0xC3, 0x19, 0x2E, 0xEE, 0x94, 0xBE, 0x75,
+ 0x0F, 0xA3, 0x76, 0x8B, 0x24, 0x24, 0x97, 0xFA,
+ 0xC0, 0x53, 0x24, 0xF5, 0x85, 0x02, 0x19, 0x9D,
+ 0xC5, 0x11, 0x2E, 0x6B, 0xA3, 0x26, 0xFE, 0xF7,
+ 0x55, 0xD4, 0x23, 0x0A, 0x73, 0x3F, 0x37, 0x53,
+ 0xEA, 0xC2, 0xB7, 0xC1, 0xC9, 0xD8, 0xF3, 0x2F,
+ 0x78, 0x76, 0x4A, 0xA0, 0x69, 0x60, 0x91, 0xC2,
+ 0x7D, 0x11, 0x74, 0xEF, 0x96, 0xD9, 0x74, 0x53,
+ 0xB1, 0x1C, 0xB0, 0xC4, 0x32, 0x16, 0x82, 0x3B,
+ 0xAF, 0x61, 0xB2, 0xDE, 0x38, 0x87, 0x3E, 0x37,
+ 0x4B, 0xA3, 0x95, 0x88, 0x8E, 0xE0, 0x27, 0x9A,
+ 0x1F, 0x7D, 0xB8, 0x23, 0xC3, 0x63, 0xE8, 0x68,
+ 0x51, 0xD9, 0x8C, 0x4C, 0xC2, 0x59, 0x86, 0x49,
+ 0xF7, 0x46, 0x9E, 0x3C, 0xD7, 0x9F, 0x89, 0x23,
+ 0xB4, 0x73, 0x35, 0x2F, 0x18, 0x23, 0x76, 0xA3,
+ 0x9F, 0x40, 0x0B, 0x76, 0x90, 0x85, 0xC8, 0x89,
+ 0xDA, 0x65, 0xE7, 0x6E, 0xEF, 0x2E, 0xF5, 0x67
+};
+
+static const unsigned char Dummy_rsa_privExp[256] = //Dummy_rsa_privExp
+{
+ 0xE3, 0xC6, 0x76, 0x57, 0x2E, 0xCB, 0xA5, 0xE6,
+ 0x0C, 0x01, 0xBD, 0x5C, 0x32, 0x2D, 0x90, 0xE0,
+ 0xFF, 0x9A, 0x80, 0xE8, 0x66, 0x8D, 0x84, 0xDC,
+ 0xF7, 0x75, 0x5F, 0x3F, 0x98, 0x7C, 0x97, 0x40,
+ 0x20, 0x21, 0xB7, 0x24, 0xC0, 0x61, 0x2D, 0x83,
+ 0xB0, 0x91, 0x8E, 0xE3, 0xC2, 0xD0, 0x2C, 0xA1,
+ 0x2C, 0x99, 0x4F, 0x48, 0xF7, 0x4E, 0x13, 0xD3,
+ 0x01, 0x71, 0x25, 0x9B, 0x3C, 0x75, 0x7C, 0xC4,
+ 0xE5, 0x89, 0x7E, 0xDA, 0xF9, 0x99, 0x5C, 0x83,
+ 0xE4, 0xDD, 0x36, 0x62, 0x5B, 0x0E, 0x12, 0x91,
+ 0xD6, 0x39, 0x45, 0x69, 0x62, 0x20, 0xCA, 0xF4,
+ 0xBA, 0x6B, 0x28, 0x1A, 0x7C, 0xBF, 0xB9, 0x97,
+ 0x37, 0x46, 0xC2, 0x7A, 0xCF, 0x10, 0x68, 0xC2,
+ 0xC9, 0xF1, 0x48, 0xDA, 0x8A, 0x2F, 0x4C, 0xBC,
+ 0x3B, 0x1C, 0xB8, 0x8F, 0x04, 0x7F, 0xFD, 0x9D,
+ 0xE2, 0x0A, 0xD2, 0x09, 0x39, 0xC7, 0xD9, 0x81,
+ 0x59, 0x17, 0x73, 0xB2, 0xEC, 0xEB, 0x36, 0x67,
+ 0xA5, 0xA8, 0xD5, 0x71, 0xD9, 0x38, 0x6A, 0xD1,
+ 0x28, 0xB9, 0x46, 0x85, 0x3A, 0x81, 0x85, 0x4E,
+ 0x55, 0xA7, 0x74, 0x79, 0xBB, 0xC5, 0x97, 0xF7,
+ 0xEF, 0xE0, 0x81, 0x20, 0xE0, 0xEA, 0x45, 0x8F,
+ 0xED, 0x70, 0x8E, 0xD6, 0xFF, 0x49, 0xCF, 0x7F,
+ 0xF2, 0xFF, 0x22, 0x20, 0x3F, 0xE9, 0x92, 0x99,
+ 0xDE, 0x81, 0xD6, 0x27, 0xF7, 0xB8, 0x3A, 0x1D,
+ 0x4F, 0xA2, 0x50, 0xFB, 0xA5, 0xE7, 0x98, 0x08,
+ 0xB5, 0x2B, 0xA2, 0x94, 0xA9, 0x17, 0x1A, 0xA8,
+ 0x34, 0xF6, 0x5E, 0x24, 0x2D, 0x40, 0x2F, 0xCB,
+ 0x3C, 0xB0, 0xF8, 0x7E, 0x84, 0xB4, 0x87, 0x82,
+ 0x19, 0xAF, 0x87, 0xB6, 0xFA, 0xA9, 0x67, 0x27,
+ 0x07, 0x28, 0xBA, 0x2E, 0xA5, 0x8E, 0xDD, 0xE5,
+ 0xD4, 0xFD, 0x06, 0x09, 0xDF, 0xBD, 0x87, 0x95,
+ 0x95, 0x25, 0x05, 0x5E, 0xB2, 0x00, 0x18, 0x41
+};
+
+static const unsigned char Dummy_rsa_pubMod[256] = //Dummy_rsa_pubMod
+{
+ 0xE6, 0x64, 0x06, 0x6C, 0x49, 0x6B, 0xEC, 0xEE,
+ 0x59, 0xAE, 0x11, 0x92, 0xF1, 0x03, 0x43, 0x87,
+ 0x8E, 0xEB, 0x4D, 0x70, 0xA9, 0x71, 0xB4, 0x6D,
+ 0x25, 0x19, 0x02, 0x4A, 0x9E, 0x4D, 0xA3, 0x10,
+ 0xFD, 0xB2, 0x27, 0x56, 0xA3, 0xFB, 0xDD, 0xE5,
+ 0xE4, 0x4E, 0xE0, 0x62, 0x8F, 0xC3, 0x2E, 0xEE,
+ 0x8F, 0x9D, 0x4D, 0x6E, 0x00, 0xDB, 0x88, 0x49,
+ 0xA2, 0xFC, 0x30, 0xFE, 0x94, 0xF3, 0x06, 0x92,
+ 0x75, 0x61, 0x11, 0x1D, 0x24, 0x07, 0xE9, 0x12,
+ 0xB6, 0xB1, 0x57, 0xF5, 0xDC, 0x01, 0xF7, 0x54,
+ 0xBF, 0xC3, 0xAC, 0x8C, 0x73, 0x2C, 0x73, 0x17,
+ 0x8E, 0xBF, 0x2F, 0x68, 0x3C, 0x61, 0x75, 0x32,
+ 0x15, 0x39, 0x93, 0xDD, 0xBA, 0x12, 0x42, 0xD3,
+ 0x25, 0x85, 0xFA, 0xA6, 0x4B, 0xAF, 0x81, 0x4B,
+ 0xCA, 0xD2, 0x9C, 0xF1, 0x3D, 0x37, 0xAE, 0xB9,
+ 0xFD, 0x77, 0x59, 0x78, 0xB9, 0x32, 0x95, 0x19,
+ 0xD1, 0x47, 0xE1, 0xC6, 0xE1, 0x16, 0x13, 0x5D,
+ 0xCC, 0x99, 0x31, 0x63, 0xAD, 0xBB, 0xA5, 0x4F,
+ 0xE4, 0x41, 0x67, 0xFD, 0x7F, 0x1E, 0xA8, 0x9A,
+ 0x35, 0x65, 0xEB, 0xC4, 0x4D, 0xD4, 0xC4, 0x29,
+ 0x0F, 0x40, 0x95, 0xFD, 0x8A, 0x30, 0x67, 0x79,
+ 0xFB, 0xD4, 0x76, 0x6F, 0xD1, 0xDE, 0x8C, 0x72,
+ 0x32, 0x05, 0x97, 0x5A, 0x26, 0x0D, 0x37, 0xCA,
+ 0x12, 0x2C, 0xDC, 0x14, 0x3F, 0xD3, 0x59, 0x00,
+ 0x66, 0xD2, 0x8E, 0xF5, 0x6E, 0x22, 0x08, 0x63,
+ 0x59, 0xB5, 0x3F, 0xBB, 0x3A, 0x4D, 0xD4, 0xD1,
+ 0xC1, 0x21, 0xA7, 0x4D, 0x02, 0x96, 0x08, 0xF5,
+ 0x2B, 0x11, 0xE5, 0x85, 0xD2, 0x6E, 0x91, 0xD6,
+ 0x8F, 0x77, 0x72, 0xEF, 0x37, 0xE3, 0x79, 0x19,
+ 0xA9, 0xEE, 0x58, 0x5D, 0x52, 0x9B, 0x2D, 0x47,
+ 0x7D, 0x27, 0xB8, 0xC3, 0x76, 0xCA, 0xDA, 0xC2,
+ 0xF4, 0xFC, 0xF4, 0x53, 0x7C, 0xD8, 0x43, 0x87
+};
+
+//Certificates
+static const unsigned char ca4_dpki_cert[0x400] =
+{
+ 0x00, 0x01, 0x00, 0x03, 0x19, 0x49, 0x42, 0x9D,
+ 0x1E, 0x58, 0xA6, 0x2E, 0x7E, 0x8B, 0x56, 0xD1,
+ 0xB7, 0x6A, 0xE3, 0x02, 0xFD, 0x8B, 0x97, 0x49,
+ 0x1F, 0x77, 0x87, 0x45, 0xF7, 0x53, 0x88, 0xC4,
+ 0xDD, 0x0B, 0xEB, 0x1D, 0xF1, 0x22, 0xFB, 0x96,
+ 0x42, 0x15, 0x14, 0x97, 0x76, 0x4A, 0x53, 0xCF,
+ 0x78, 0x15, 0x18, 0x45, 0xE4, 0x2C, 0xA8, 0xFD,
+ 0xE4, 0x86, 0xFD, 0x2A, 0x4F, 0x53, 0xF8, 0xA1,
+ 0xBA, 0x00, 0x8A, 0x74, 0x85, 0xFF, 0x73, 0xB3,
+ 0xBF, 0x7E, 0x3C, 0x98, 0x07, 0x29, 0xD0, 0x65,
+ 0x6B, 0x69, 0x32, 0x19, 0xAD, 0xE8, 0x35, 0xEB,
+ 0x5F, 0xFF, 0xFC, 0xCB, 0x7C, 0xBB, 0x5E, 0x30,
+ 0x7F, 0xE0, 0x68, 0x8B, 0x88, 0x8E, 0xF2, 0xD2,
+ 0x05, 0x3F, 0xB7, 0xE7, 0x91, 0xE9, 0x85, 0xFD,
+ 0x15, 0xEF, 0x10, 0xD7, 0x9C, 0xCA, 0x88, 0xD6,
+ 0xBB, 0x15, 0xE8, 0xE4, 0x71, 0x4A, 0x98, 0xEE,
+ 0x09, 0xBF, 0x7B, 0x8A, 0xF0, 0x53, 0x23, 0x2B,
+ 0x64, 0x50, 0xE6, 0xD5, 0xFD, 0xFF, 0xC2, 0x0A,
+ 0x6D, 0x1E, 0xA6, 0xA2, 0x38, 0x12, 0xE1, 0x01,
+ 0x45, 0x25, 0xD5, 0x6D, 0x40, 0x82, 0x70, 0x3B,
+ 0x86, 0x98, 0x69, 0x59, 0xA7, 0x3C, 0xD1, 0xA1,
+ 0x43, 0x64, 0xD2, 0xC2, 0xDA, 0xEA, 0x96, 0xB0,
+ 0x95, 0xF7, 0x6C, 0x46, 0xE4, 0xFF, 0x41, 0x55,
+ 0x46, 0x5E, 0x70, 0xEF, 0x1E, 0xD3, 0x10, 0x53,
+ 0xD9, 0x70, 0x11, 0xE0, 0x10, 0xCC, 0x93, 0xE7,
+ 0x91, 0x40, 0x13, 0x68, 0x7F, 0xA3, 0xA8, 0x02,
+ 0x99, 0x6D, 0x1E, 0x55, 0x7B, 0x1C, 0xCC, 0x7A,
+ 0x7E, 0x8F, 0x58, 0x65, 0xC1, 0x74, 0x2E, 0x28,
+ 0xE2, 0x6D, 0xEF, 0x38, 0xA9, 0x3A, 0xB5, 0xD8,
+ 0x2D, 0x43, 0xEC, 0xCC, 0xBF, 0x0B, 0xEF, 0x22,
+ 0xE1, 0xFD, 0x57, 0xE2, 0x86, 0x43, 0x33, 0x58,
+ 0x2F, 0xED, 0xEA, 0xBC, 0x01, 0x2F, 0x98, 0x6D,
+ 0xDF, 0xC3, 0xE9, 0x44, 0x79, 0x73, 0x47, 0x03,
+ 0x08, 0x45, 0x5B, 0xDC, 0x57, 0xAA, 0x17, 0x0B,
+ 0x84, 0x42, 0x7F, 0x73, 0xA2, 0x9B, 0x48, 0xF6,
+ 0xDA, 0x13, 0x5F, 0x66, 0xC7, 0x45, 0xC1, 0x42,
+ 0xA8, 0x4A, 0xFB, 0x0E, 0x6A, 0x5E, 0xED, 0x85,
+ 0xD7, 0xB9, 0x71, 0x99, 0x36, 0xF8, 0xCE, 0x2B,
+ 0x62, 0x1F, 0x39, 0x5F, 0x40, 0xDC, 0x03, 0xBE,
+ 0xF8, 0x85, 0x4C, 0x11, 0x17, 0xFF, 0x0C, 0x12,
+ 0x86, 0x41, 0xCC, 0x78, 0x43, 0xB9, 0x7B, 0x43,
+ 0x46, 0xDB, 0x22, 0x6F, 0x60, 0x26, 0xAC, 0xB5,
+ 0x6C, 0x27, 0x8B, 0x8E, 0x0E, 0xA7, 0x9A, 0x2D,
+ 0x65, 0xEF, 0x79, 0x8E, 0x10, 0x78, 0xAD, 0x80,
+ 0xED, 0x4B, 0x96, 0x04, 0xD2, 0xF0, 0x8B, 0x2C,
+ 0xD6, 0x4A, 0x23, 0xA3, 0xDB, 0x27, 0x08, 0x33,
+ 0xB4, 0x02, 0xF8, 0x08, 0x51, 0xF3, 0x5B, 0xED,
+ 0x3E, 0xE4, 0x57, 0x7C, 0x66, 0x60, 0xFB, 0xF1,
+ 0x6D, 0x94, 0x13, 0xE0, 0x9C, 0x91, 0x7A, 0x49,
+ 0xD4, 0x2C, 0x6D, 0xA3, 0x75, 0xBC, 0x27, 0xF0,
+ 0x23, 0x0D, 0xB9, 0x8F, 0x89, 0x73, 0xAB, 0x02,
+ 0x7B, 0x52, 0x2C, 0xD5, 0x7E, 0xC0, 0x3D, 0x25,
+ 0xE8, 0xB3, 0xFC, 0x34, 0x94, 0xC9, 0x7F, 0xB1,
+ 0x08, 0xFE, 0x18, 0xC6, 0x8A, 0x43, 0x36, 0xE4,
+ 0x6C, 0x26, 0xB6, 0xF2, 0x80, 0xD2, 0x7E, 0x34,
+ 0xBE, 0x28, 0x7C, 0x3E, 0x46, 0x87, 0xBC, 0x9D,
+ 0x77, 0x6B, 0x76, 0xD9, 0x28, 0xD1, 0xB6, 0x35,
+ 0x2E, 0xC0, 0x34, 0x7D, 0x72, 0x94, 0xAA, 0x93,
+ 0x60, 0x26, 0x8D, 0x26, 0xF5, 0xF6, 0x52, 0x06,
+ 0x4A, 0xF2, 0x40, 0xD7, 0xD0, 0x0C, 0x7C, 0x5E,
+ 0xA3, 0xC3, 0x2D, 0xE6, 0x2D, 0x9B, 0x5C, 0x4B,
+ 0x4C, 0xAB, 0x6F, 0xD7, 0xBD, 0x37, 0x1D, 0x57,
+ 0xC2, 0x16, 0x60, 0x95, 0x91, 0x0E, 0x4A, 0xD8,
+ 0xE9, 0xED, 0x18, 0x1E, 0xF7, 0x61, 0x93, 0x61,
+ 0x53, 0x89, 0x2D, 0x77, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x52, 0x6F, 0x6F, 0x74, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x43, 0x41, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x81, 0x12, 0x2A, 0x46,
+ 0xC9, 0xCC, 0x2D, 0xC4, 0xDF, 0x29, 0x30, 0xE4,
+ 0xDF, 0x3F, 0x8C, 0x70, 0xA0, 0x78, 0x94, 0x87,
+ 0x75, 0xAD, 0x5E, 0x9A, 0xA6, 0x04, 0xC5, 0xB4,
+ 0xD8, 0xEA, 0xFF, 0x2A, 0xA1, 0xD2, 0x14, 0x67,
+ 0x65, 0x64, 0xEF, 0xCA, 0x28, 0xCC, 0x00, 0x15,
+ 0x45, 0x54, 0xA1, 0xA3, 0xEA, 0x13, 0x79, 0xE9,
+ 0xE6, 0xCA, 0xAC, 0xED, 0x15, 0x93, 0xFE, 0x88,
+ 0xD8, 0x9A, 0xC6, 0xB8, 0xAC, 0xCC, 0xAB, 0x6E,
+ 0x20, 0x7C, 0xEB, 0x7C, 0xCA, 0x29, 0x80, 0x9E,
+ 0x29, 0x80, 0x44, 0x06, 0x62, 0xB7, 0xD4, 0x38,
+ 0x2A, 0x15, 0xDA, 0x43, 0x08, 0x57, 0x45, 0xA9,
+ 0xAA, 0xE5, 0x9A, 0xA0, 0x5B, 0xDB, 0x32, 0xF6,
+ 0x68, 0x69, 0xA2, 0xDD, 0x42, 0x95, 0x38, 0x6C,
+ 0x87, 0xEC, 0xDD, 0x35, 0x08, 0xA2, 0xCF, 0x60,
+ 0xD0, 0x1E, 0x23, 0xEC, 0x2F, 0xE6, 0x98, 0xF4,
+ 0x70, 0xD6, 0x00, 0x15, 0x49, 0xA2, 0xF0, 0x67,
+ 0x59, 0x13, 0x1E, 0x53, 0x4C, 0x70, 0x06, 0x05,
+ 0x7D, 0xEF, 0x1D, 0x18, 0xA8, 0x3F, 0x0A, 0xC7,
+ 0x9C, 0xFE, 0x80, 0xFF, 0x5A, 0x91, 0xF2, 0xBE,
+ 0xD4, 0xA0, 0x83, 0x70, 0x61, 0x19, 0x0A, 0x03,
+ 0x29, 0x90, 0x21, 0x65, 0x40, 0x3C, 0x9A, 0x90,
+ 0x8F, 0xB6, 0x15, 0x73, 0x9F, 0x3C, 0xE3, 0x3B,
+ 0xF1, 0xBA, 0xEA, 0x16, 0xC2, 0x5B, 0xCE, 0xD7,
+ 0x96, 0x3F, 0xAC, 0xC9, 0xD2, 0x4D, 0x9C, 0x0A,
+ 0xD7, 0x6F, 0xC0, 0x20, 0xB2, 0xC4, 0xB8, 0x4C,
+ 0x10, 0xA7, 0x41, 0xA2, 0xCC, 0x7D, 0x9B, 0xAC,
+ 0x3A, 0xAC, 0xCC, 0xA3, 0x52, 0x9B, 0xAC, 0x31,
+ 0x6A, 0x9A, 0xA7, 0x5D, 0x2A, 0x26, 0xC7, 0xD7,
+ 0xD2, 0x88, 0xCB, 0xA4, 0x66, 0xC5, 0xFE, 0x5F,
+ 0x45, 0x4A, 0xE6, 0x79, 0x74, 0x4A, 0x90, 0xA1,
+ 0x57, 0x72, 0xDB, 0x3B, 0x0E, 0x47, 0xA4, 0x9A,
+ 0xF0, 0x31, 0xD1, 0x6D, 0xBE, 0xAB, 0x33, 0x2B,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char xs9_dpki_cert[0x300] =
+{
+ 0x00, 0x01, 0x00, 0x04, 0x63, 0x80, 0x5A, 0x35,
+ 0x1A, 0x43, 0x7B, 0xA2, 0x43, 0x19, 0xBB, 0x3A,
+ 0x77, 0x7B, 0x7A, 0xF3, 0x5E, 0x72, 0x4B, 0x15,
+ 0x0A, 0x06, 0x39, 0x6C, 0x5F, 0xEC, 0x38, 0x45,
+ 0xB1, 0x88, 0x76, 0x26, 0x8D, 0x5E, 0xDA, 0xE6,
+ 0x2F, 0x14, 0xBA, 0x02, 0xFA, 0xD6, 0xFC, 0x3B,
+ 0x2B, 0xBE, 0x87, 0x07, 0x63, 0x8E, 0x55, 0xBF,
+ 0x05, 0x5A, 0xFC, 0xFC, 0xB3, 0x47, 0x69, 0x11,
+ 0x89, 0xDB, 0x1C, 0xAF, 0x4B, 0x43, 0x76, 0x62,
+ 0x3E, 0x30, 0x89, 0x0A, 0x9D, 0x3B, 0xBB, 0x3E,
+ 0x50, 0xBD, 0xF7, 0xA6, 0xC0, 0xF7, 0xF8, 0xBB,
+ 0x0D, 0xB5, 0x6A, 0xBB, 0xC6, 0xC3, 0x50, 0xC8,
+ 0x88, 0xBB, 0x9D, 0xF0, 0x9B, 0xD1, 0x30, 0x64,
+ 0x60, 0x69, 0xDD, 0x34, 0x67, 0xA7, 0x00, 0xEB,
+ 0xDC, 0xF9, 0x8C, 0xB0, 0xF7, 0x93, 0x0E, 0x81,
+ 0xFE, 0x98, 0xD9, 0x72, 0x45, 0x8B, 0x94, 0x7E,
+ 0x59, 0xE2, 0xBE, 0x4E, 0x91, 0x2D, 0x75, 0xCA,
+ 0x1B, 0x8E, 0x2E, 0xF4, 0x6D, 0x73, 0xB1, 0x6B,
+ 0x35, 0xB5, 0x67, 0x0D, 0x63, 0x2D, 0x51, 0x38,
+ 0x53, 0x28, 0x19, 0x1D, 0x9D, 0xAE, 0x8D, 0xC6,
+ 0x61, 0xCC, 0xEF, 0xA4, 0xAB, 0xE2, 0xF3, 0xB0,
+ 0x4C, 0x7B, 0xE2, 0x71, 0xB5, 0xF9, 0x2C, 0xFA,
+ 0x55, 0xCD, 0x88, 0x8B, 0x72, 0xCC, 0xBE, 0x67,
+ 0xFA, 0xDF, 0xEF, 0x6B, 0x53, 0x3C, 0x45, 0xD8,
+ 0xCB, 0xDF, 0xB2, 0x76, 0x41, 0x46, 0xD6, 0xC2,
+ 0x6F, 0x27, 0x16, 0xC5, 0x07, 0xF3, 0xF4, 0x44,
+ 0x66, 0xA3, 0x15, 0xD2, 0x77, 0xF2, 0x89, 0xDA,
+ 0xFD, 0xD5, 0x50, 0xCF, 0xA4, 0x9B, 0xEA, 0xCA,
+ 0xC9, 0x7B, 0xE5, 0x46, 0x0E, 0xED, 0x9B, 0xFB,
+ 0x04, 0xA9, 0xDA, 0x19, 0x58, 0xD9, 0x2A, 0x20,
+ 0x8A, 0xAC, 0xC1, 0xF4, 0x8E, 0xE9, 0x14, 0xD8,
+ 0x8A, 0xD7, 0x41, 0xD5, 0x5B, 0x9B, 0x64, 0x22,
+ 0xD8, 0xAF, 0xAE, 0xC7, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x43, 0x41, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x58, 0x53, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x39, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0xA3, 0x47, 0xA4,
+ 0xC0, 0x84, 0x4C, 0xEB, 0x7E, 0xB0, 0xCF, 0xF0,
+ 0xAE, 0xB7, 0x77, 0x69, 0x85, 0x93, 0xE4, 0x99,
+ 0x5A, 0x95, 0x4E, 0x58, 0x17, 0x38, 0xCE, 0xD6,
+ 0x81, 0xB0, 0xBD, 0x77, 0x09, 0xE7, 0xF8, 0x9A,
+ 0xDF, 0xAD, 0x05, 0x48, 0x83, 0xF6, 0xC3, 0xFD,
+ 0xDF, 0x7B, 0x83, 0xE0, 0x0C, 0x26, 0x81, 0x54,
+ 0x43, 0x29, 0xEA, 0x82, 0x6C, 0x89, 0xF0, 0xA6,
+ 0x74, 0x42, 0x86, 0x4D, 0x32, 0x60, 0x32, 0x7D,
+ 0xA7, 0x7A, 0x13, 0x40, 0x66, 0x59, 0xDA, 0x3E,
+ 0x41, 0x6B, 0x27, 0x94, 0x03, 0x4F, 0xAA, 0x22,
+ 0x9D, 0xD5, 0x54, 0x52, 0xDB, 0x27, 0x0A, 0x6A,
+ 0xA2, 0x3D, 0x19, 0xB1, 0x66, 0x1B, 0x19, 0x7D,
+ 0xAB, 0xC7, 0x0E, 0x88, 0x17, 0x91, 0xA1, 0x2A,
+ 0xB4, 0x3C, 0x6C, 0xCB, 0xF5, 0xAA, 0x7C, 0x3A,
+ 0xDD, 0x36, 0xFB, 0x35, 0x71, 0x7B, 0x20, 0x01,
+ 0x59, 0x00, 0xD6, 0xF6, 0x90, 0x39, 0x35, 0x41,
+ 0x31, 0xF8, 0xC1, 0xC0, 0x57, 0x3A, 0x35, 0x18,
+ 0x58, 0x90, 0xB1, 0xAD, 0x9A, 0x0E, 0xEC, 0xE0,
+ 0xF4, 0x7A, 0x7D, 0xA5, 0x27, 0x48, 0xC9, 0x72,
+ 0xAB, 0x0D, 0x08, 0x7B, 0x62, 0x35, 0x40, 0x91,
+ 0x14, 0x2B, 0xB1, 0x1D, 0x1A, 0xFA, 0xF9, 0xCD,
+ 0x5C, 0x17, 0x13, 0x53, 0x52, 0x71, 0xCA, 0xE2,
+ 0x2A, 0x78, 0xB1, 0x7F, 0x4A, 0xCD, 0x59, 0xD8,
+ 0xBA, 0x1D, 0x7D, 0x70, 0x5F, 0x78, 0x1B, 0x9F,
+ 0x9D, 0x37, 0x18, 0x8E, 0xD7, 0xCD, 0x0D, 0x49,
+ 0x57, 0x74, 0x69, 0x88, 0x3A, 0x6B, 0x8E, 0x4E,
+ 0x1B, 0x85, 0xDD, 0xBE, 0x39, 0x45, 0x05, 0x89,
+ 0x56, 0x12, 0x97, 0x59, 0x9A, 0x09, 0xA4, 0xC8,
+ 0x2D, 0x2F, 0xF5, 0xCF, 0xB4, 0x73, 0x70, 0xDB,
+ 0x58, 0x1E, 0xB2, 0x4E, 0x77, 0x6F, 0xA4, 0x7E,
+ 0x62, 0xDF, 0xB7, 0x05, 0xE8, 0x80, 0x42, 0x5C,
+ 0xB8, 0x78, 0x87, 0x97, 0x7F, 0x66, 0x2C, 0x5F,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char cpA_dpki_cert[0x300] =
+{
+ 0x00, 0x01, 0x00, 0x04, 0x50, 0x05, 0xD7, 0x5E,
+ 0x6D, 0xDE, 0xB8, 0x78, 0x3C, 0x81, 0xE9, 0xEF,
+ 0x0D, 0x17, 0xCD, 0x58, 0xF5, 0x94, 0x26, 0xA3,
+ 0xFD, 0x6F, 0x69, 0x90, 0xE8, 0xF8, 0x32, 0x87,
+ 0x12, 0x2E, 0xC2, 0x5C, 0xA1, 0x4B, 0x99, 0x24,
+ 0x23, 0x37, 0xBA, 0x91, 0xA7, 0x5B, 0x0F, 0x7C,
+ 0x59, 0xFB, 0xF7, 0xD1, 0x89, 0x27, 0x22, 0xC4,
+ 0xE6, 0xAF, 0xC7, 0xDE, 0xC7, 0x4A, 0x6E, 0x00,
+ 0x7F, 0x43, 0x4A, 0x88, 0x8A, 0x82, 0x15, 0xE8,
+ 0xDF, 0x2B, 0x52, 0xED, 0x42, 0x00, 0xBC, 0x69,
+ 0xB4, 0xDA, 0x7F, 0xEB, 0x74, 0x6C, 0x7A, 0x2D,
+ 0x96, 0x56, 0x5B, 0x45, 0x59, 0x7B, 0x8F, 0xAE,
+ 0xB1, 0x6B, 0xDC, 0x76, 0xC1, 0xC8, 0x0C, 0x47,
+ 0xF5, 0x0D, 0xA9, 0xC3, 0xE1, 0xFE, 0x28, 0x50,
+ 0x1C, 0x26, 0xA2, 0xD1, 0x54, 0x4B, 0xD1, 0x60,
+ 0x4A, 0x9E, 0x8F, 0x32, 0x2A, 0xEF, 0x31, 0x5F,
+ 0xEA, 0x48, 0x22, 0x67, 0x22, 0xB7, 0xCB, 0x37,
+ 0x2F, 0xF3, 0x5F, 0x5E, 0x61, 0x6A, 0x53, 0x44,
+ 0xA5, 0x85, 0xE5, 0xA0, 0x8A, 0x2E, 0x17, 0x77,
+ 0x57, 0x2B, 0x7A, 0x9A, 0xF7, 0xD2, 0xD8, 0xC4,
+ 0x9C, 0xD0, 0xA0, 0x54, 0xBF, 0x8A, 0x9D, 0xB4,
+ 0x9F, 0xC6, 0x60, 0x61, 0x7C, 0xB8, 0x35, 0x4E,
+ 0x25, 0x7F, 0x68, 0x68, 0x2F, 0x94, 0xB3, 0xCC,
+ 0x53, 0x8C, 0x42, 0x6F, 0x88, 0xC5, 0x48, 0x5C,
+ 0xBE, 0xC1, 0xD0, 0x48, 0x04, 0x74, 0x96, 0x5A,
+ 0x7E, 0x82, 0x59, 0xAA, 0x9F, 0xB6, 0x61, 0x46,
+ 0xCE, 0x59, 0x21, 0xC6, 0xF0, 0xC1, 0x75, 0x1F,
+ 0x21, 0x91, 0x7F, 0x24, 0x96, 0xCB, 0x0C, 0x70,
+ 0x15, 0x7A, 0xB7, 0xBB, 0x3A, 0x9F, 0x57, 0x56,
+ 0x56, 0x5C, 0x38, 0x92, 0x2E, 0xFD, 0xC8, 0xF1,
+ 0x70, 0xB9, 0xAE, 0xA1, 0xAE, 0x36, 0xF5, 0x5E,
+ 0x35, 0x26, 0x63, 0x0A, 0xBA, 0xB2, 0x05, 0x0F,
+ 0xF0, 0x0C, 0xDC, 0xBB, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x43, 0x41, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x43, 0x50, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x61, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0xA3, 0x4D, 0x5B,
+ 0xAA, 0x7F, 0x93, 0x80, 0x28, 0x9B, 0xE8, 0x98,
+ 0x63, 0x10, 0x7A, 0xE1, 0x0C, 0x59, 0x2C, 0x2F,
+ 0x7C, 0xFF, 0xBD, 0xAA, 0xDD, 0x74, 0xF4, 0xA2,
+ 0xFB, 0xAC, 0xD7, 0x6F, 0x00, 0x93, 0x42, 0x06,
+ 0x34, 0x71, 0x56, 0xD8, 0x40, 0x49, 0x72, 0x9F,
+ 0x3E, 0x24, 0xFA, 0x5E, 0x19, 0xD1, 0x5B, 0x63,
+ 0x5C, 0xD2, 0xEF, 0x09, 0xDE, 0x32, 0xEE, 0x6B,
+ 0x6F, 0xC8, 0xFA, 0x32, 0x8E, 0x2E, 0x96, 0xB9,
+ 0x94, 0x41, 0x04, 0x7D, 0x07, 0x62, 0x95, 0xDA,
+ 0x0D, 0x91, 0xD8, 0x09, 0x35, 0xD0, 0xDE, 0x8E,
+ 0x6B, 0xC6, 0xAB, 0x14, 0x27, 0x01, 0x9C, 0xFE,
+ 0x49, 0x96, 0xFC, 0x9B, 0x54, 0x79, 0x4D, 0xEB,
+ 0xD7, 0xC6, 0x66, 0x73, 0xA6, 0xDD, 0x3A, 0x77,
+ 0x65, 0x47, 0x94, 0xEC, 0x1C, 0x87, 0xAA, 0x46,
+ 0xD9, 0x78, 0xA9, 0x7D, 0xDB, 0x11, 0x22, 0x6E,
+ 0xD4, 0x12, 0xC2, 0x78, 0x4B, 0x21, 0x83, 0x92,
+ 0xC7, 0x10, 0xC7, 0x74, 0x19, 0xFF, 0xAA, 0xF6,
+ 0x0B, 0x75, 0xD8, 0x23, 0xDD, 0x33, 0xC3, 0xA1,
+ 0x5B, 0xA7, 0x2D, 0x30, 0xA5, 0xA4, 0xD8, 0xF8,
+ 0x0F, 0xD6, 0x73, 0xFD, 0x26, 0xCB, 0x29, 0xA6,
+ 0xEF, 0x50, 0x39, 0xE2, 0x5F, 0x59, 0x61, 0x84,
+ 0x6B, 0xDA, 0x2E, 0xC7, 0xCB, 0xE4, 0x38, 0x4B,
+ 0x28, 0xFB, 0x0D, 0xD5, 0x8E, 0x7C, 0xAA, 0x7D,
+ 0x4B, 0x37, 0x3A, 0xD7, 0x81, 0xDD, 0x73, 0xE3,
+ 0x09, 0x93, 0xBD, 0xBD, 0x7E, 0x08, 0x55, 0x4A,
+ 0x8C, 0xA5, 0xC9, 0x84, 0x2D, 0x71, 0x01, 0xA2,
+ 0x2A, 0x01, 0xB0, 0x15, 0xFB, 0x30, 0x78, 0xB9,
+ 0x13, 0xF4, 0xC7, 0x3F, 0xB5, 0xA6, 0xF1, 0xA2,
+ 0x5E, 0x22, 0xB0, 0x02, 0xB6, 0xE0, 0x09, 0x54,
+ 0x7F, 0x0F, 0xBD, 0xF0, 0xFE, 0xA5, 0x50, 0x1D,
+ 0x93, 0x15, 0xF9, 0x3D, 0x83, 0x0F, 0x0F, 0x0E,
+ 0x3D, 0xE2, 0x3D, 0x96, 0xE7, 0x09, 0xD9, 0x77,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+#endif
\ No newline at end of file
diff --git a/keys_retail.h b/keys_retail.h
new file mode 100644
index 0000000..ecf86ce
--- /dev/null
+++ b/keys_retail.h
@@ -0,0 +1,557 @@
+#ifndef _KEYS_RETAIL_H_
+#define _KEYS_RETAIL_H_
+
+// AES KEYS
+static const unsigned char zeros_fixed_aesKey[16] = //zeros_fixed_aesKey
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+// RSA KEYS
+static const unsigned char cert_root_rsa_pubk[0x200] =
+{
+ 0xF8, 0x24, 0x6C, 0x58, 0xBA, 0xE7, 0x50, 0x03,
+ 0x01, 0xFB, 0xB7, 0xC2, 0xEB, 0xE0, 0x01, 0x05,
+ 0x71, 0xDA, 0x92, 0x23, 0x78, 0xF0, 0x51, 0x4E,
+ 0xC0, 0x03, 0x1D, 0xD0, 0xD2, 0x1E, 0xD3, 0xD0,
+ 0x7E, 0xFC, 0x85, 0x20, 0x69, 0xB5, 0xDE, 0x9B,
+ 0xB9, 0x51, 0xA8, 0xBC, 0x90, 0xA2, 0x44, 0x92,
+ 0x6D, 0x37, 0x92, 0x95, 0xAE, 0x94, 0x36, 0xAA,
+ 0xA6, 0xA3, 0x02, 0x51, 0x0C, 0x7B, 0x1D, 0xED,
+ 0xD5, 0xFB, 0x20, 0x86, 0x9D, 0x7F, 0x30, 0x16,
+ 0xF6, 0xBE, 0x65, 0xD3, 0x83, 0xA1, 0x6D, 0xB3,
+ 0x32, 0x1B, 0x95, 0x35, 0x18, 0x90, 0xB1, 0x70,
+ 0x02, 0x93, 0x7E, 0xE1, 0x93, 0xF5, 0x7E, 0x99,
+ 0xA2, 0x47, 0x4E, 0x9D, 0x38, 0x24, 0xC7, 0xAE,
+ 0xE3, 0x85, 0x41, 0xF5, 0x67, 0xE7, 0x51, 0x8C,
+ 0x7A, 0x0E, 0x38, 0xE7, 0xEB, 0xAF, 0x41, 0x19,
+ 0x1B, 0xCF, 0xF1, 0x7B, 0x42, 0xA6, 0xB4, 0xED,
+ 0xE6, 0xCE, 0x8D, 0xE7, 0x31, 0x8F, 0x7F, 0x52,
+ 0x04, 0xB3, 0x99, 0x0E, 0x22, 0x67, 0x45, 0xAF,
+ 0xD4, 0x85, 0xB2, 0x44, 0x93, 0x00, 0x8B, 0x08,
+ 0xC7, 0xF6, 0xB7, 0xE5, 0x6B, 0x02, 0xB3, 0xE8,
+ 0xFE, 0x0C, 0x9D, 0x85, 0x9C, 0xB8, 0xB6, 0x82,
+ 0x23, 0xB8, 0xAB, 0x27, 0xEE, 0x5F, 0x65, 0x38,
+ 0x07, 0x8B, 0x2D, 0xB9, 0x1E, 0x2A, 0x15, 0x3E,
+ 0x85, 0x81, 0x80, 0x72, 0xA2, 0x3B, 0x6D, 0xD9,
+ 0x32, 0x81, 0x05, 0x4F, 0x6F, 0xB0, 0xF6, 0xF5,
+ 0xAD, 0x28, 0x3E, 0xCA, 0x0B, 0x7A, 0xF3, 0x54,
+ 0x55, 0xE0, 0x3D, 0xA7, 0xB6, 0x83, 0x26, 0xF3,
+ 0xEC, 0x83, 0x4A, 0xF3, 0x14, 0x04, 0x8A, 0xC6,
+ 0xDF, 0x20, 0xD2, 0x85, 0x08, 0x67, 0x3C, 0xAB,
+ 0x62, 0xA2, 0xC7, 0xBC, 0x13, 0x1A, 0x53, 0x3E,
+ 0x0B, 0x66, 0x80, 0x6B, 0x1C, 0x30, 0x66, 0x4B,
+ 0x37, 0x23, 0x31, 0xBD, 0xC4, 0xB0, 0xCA, 0xD8,
+ 0xD1, 0x1E, 0xE7, 0xBB, 0xD9, 0x28, 0x55, 0x48,
+ 0xAA, 0xEC, 0x1F, 0x66, 0xE8, 0x21, 0xB3, 0xC8,
+ 0xA0, 0x47, 0x69, 0x00, 0xC5, 0xE6, 0x88, 0xE8,
+ 0x0C, 0xCE, 0x3C, 0x61, 0xD6, 0x9C, 0xBB, 0xA1,
+ 0x37, 0xC6, 0x60, 0x4F, 0x7A, 0x72, 0xDD, 0x8C,
+ 0x7B, 0x3E, 0x3D, 0x51, 0x29, 0x0D, 0xAA, 0x6A,
+ 0x59, 0x7B, 0x08, 0x1F, 0x9D, 0x36, 0x33, 0xA3,
+ 0x46, 0x7A, 0x35, 0x61, 0x09, 0xAC, 0xA7, 0xDD,
+ 0x7D, 0x2E, 0x2F, 0xB2, 0xC1, 0xAE, 0xB8, 0xE2,
+ 0x0F, 0x48, 0x92, 0xD8, 0xB9, 0xF8, 0xB4, 0x6F,
+ 0x4E, 0x3C, 0x11, 0xF4, 0xF4, 0x7D, 0x8B, 0x75,
+ 0x7D, 0xFE, 0xFE, 0xA3, 0x89, 0x9C, 0x33, 0x59,
+ 0x5C, 0x5E, 0xFD, 0xEB, 0xCB, 0xAB, 0xE8, 0x41,
+ 0x3E, 0x3A, 0x9A, 0x80, 0x3C, 0x69, 0x35, 0x6E,
+ 0xB2, 0xB2, 0xAD, 0x5C, 0xC4, 0xC8, 0x58, 0x45,
+ 0x5E, 0xF5, 0xF7, 0xB3, 0x06, 0x44, 0xB4, 0x7C,
+ 0x64, 0x06, 0x8C, 0xDF, 0x80, 0x9F, 0x76, 0x02,
+ 0x5A, 0x2D, 0xB4, 0x46, 0xE0, 0x3D, 0x7C, 0xF6,
+ 0x2F, 0x34, 0xE7, 0x02, 0x45, 0x7B, 0x02, 0xA4,
+ 0xCF, 0x5D, 0x9D, 0xD5, 0x3C, 0xA5, 0x3A, 0x7C,
+ 0xA6, 0x29, 0x78, 0x8C, 0x67, 0xCA, 0x08, 0xBF,
+ 0xEC, 0xCA, 0x43, 0xA9, 0x57, 0xAD, 0x16, 0xC9,
+ 0x4E, 0x1C, 0xD8, 0x75, 0xCA, 0x10, 0x7D, 0xCE,
+ 0x7E, 0x01, 0x18, 0xF0, 0xDF, 0x6B, 0xFE, 0xE5,
+ 0x1D, 0xDB, 0xD9, 0x91, 0xC2, 0x6E, 0x60, 0xCD,
+ 0x48, 0x58, 0xAA, 0x59, 0x2C, 0x82, 0x00, 0x75,
+ 0xF2, 0x9F, 0x52, 0x6C, 0x91, 0x7C, 0x6F, 0xE5,
+ 0x40, 0x3E, 0xA7, 0xD4, 0xA5, 0x0C, 0xEC, 0x3B,
+ 0x73, 0x84, 0xDE, 0x88, 0x6E, 0x82, 0xD2, 0xEB,
+ 0x4D, 0x4E, 0x42, 0xB5, 0xF2, 0xB1, 0x49, 0xA8,
+ 0x1E, 0xA7, 0xCE, 0x71, 0x44, 0xDC, 0x29, 0x94,
+ 0xCF, 0xC4, 0x4E, 0x1F, 0x91, 0xCB, 0xD4, 0x95
+};
+
+static const unsigned char AccessDesc_pubMod[0x100] =
+{
+ 0xB1, 0xE3, 0xE3, 0x5F, 0x01, 0x39, 0x80, 0xD1,
+ 0x56, 0x78, 0x9D, 0xB7, 0x06, 0xF7, 0x1D, 0xBF,
+ 0x3E, 0x22, 0x76, 0xED, 0xF9, 0x5D, 0xA2, 0x36,
+ 0xB6, 0x30, 0x61, 0x05, 0x96, 0xD3, 0x00, 0xB9,
+ 0xED, 0xF1, 0xD7, 0xE0, 0x1D, 0xA0, 0x4F, 0xB7,
+ 0xCF, 0x5A, 0x19, 0x87, 0x75, 0x49, 0x88, 0x40,
+ 0xED, 0xE3, 0x6F, 0x7C, 0x90, 0x4A, 0x64, 0x45,
+ 0x98, 0xD7, 0x04, 0xB9, 0x5A, 0x6B, 0x45, 0xAA,
+ 0x7E, 0x94, 0xC0, 0xB3, 0xB7, 0xDB, 0x7B, 0x66,
+ 0x59, 0x20, 0xB7, 0x08, 0xE2, 0xF3, 0x83, 0xA3,
+ 0x7F, 0xE3, 0x20, 0x21, 0xA0, 0xEB, 0xB7, 0x28,
+ 0x0F, 0xF3, 0x2B, 0x15, 0xA4, 0xC9, 0xD0, 0xAB,
+ 0x89, 0x39, 0x99, 0x7E, 0x76, 0x5F, 0x9E, 0x4D,
+ 0x1E, 0x01, 0x22, 0x8D, 0x74, 0xA6, 0xEB, 0x9A,
+ 0xA3, 0x9D, 0x45, 0xE5, 0x10, 0x61, 0x6E, 0x20,
+ 0xFD, 0x23, 0x75, 0xC0, 0xC5, 0x05, 0x03, 0xC5,
+ 0x4C, 0x02, 0x4F, 0x54, 0x4B, 0x57, 0x08, 0xB4,
+ 0x46, 0xC3, 0x2C, 0xF1, 0xF9, 0x52, 0x6C, 0xCD,
+ 0x14, 0x55, 0xA8, 0x55, 0x92, 0x6D, 0xE2, 0x4A,
+ 0x41, 0x46, 0xEB, 0x08, 0xC5, 0xF3, 0xB4, 0x8D,
+ 0x0D, 0x5E, 0x21, 0xEA, 0xAF, 0x4D, 0x27, 0x4D,
+ 0xDE, 0x77, 0x93, 0x97, 0xE2, 0xC7, 0x6B, 0x66,
+ 0x1F, 0xDB, 0x2D, 0x6E, 0xA9, 0x5F, 0x61, 0x14,
+ 0x17, 0x7B, 0x2B, 0x66, 0x5A, 0xB5, 0x01, 0x89,
+ 0xF2, 0x23, 0x75, 0x25, 0x25, 0x9C, 0x86, 0x9A,
+ 0x89, 0xFF, 0x64, 0x1D, 0x5B, 0xCE, 0xD7, 0x7E,
+ 0x3F, 0x2D, 0xA8, 0xDA, 0xB5, 0x5A, 0xC5, 0x5F,
+ 0x59, 0x20, 0xB0, 0xED, 0x1C, 0x91, 0xFF, 0xA3,
+ 0x27, 0xB8, 0x8E, 0xCF, 0x82, 0x15, 0xE5, 0x49,
+ 0xEF, 0xE4, 0x58, 0xE1, 0x5F, 0x8F, 0x53, 0xB9,
+ 0x33, 0x2A, 0x56, 0x24, 0xAA, 0xA1, 0xD3, 0x6E,
+ 0x47, 0x1A, 0x63, 0x44, 0x19, 0xB3, 0x8E, 0xA5
+};
+
+static const unsigned char RetailNcsdCfa_pubMod[0x100] =
+{
+ 0xFB, 0xDE, 0xB8, 0x2B, 0x40, 0x93, 0x0F, 0xF6,
+ 0xB1, 0x9A, 0x08, 0x06, 0x1B, 0x86, 0xFE, 0xD0,
+ 0xDF, 0x10, 0x79, 0x17, 0x3D, 0x8C, 0xE2, 0x7A,
+ 0xCE, 0x8F, 0x23, 0x45, 0xB9, 0x0A, 0x6D, 0xED,
+ 0x30, 0x0E, 0xC1, 0xA8, 0x92, 0xC4, 0xBD, 0x1A,
+ 0xCE, 0xA7, 0xAC, 0x77, 0xAA, 0x47, 0xE5, 0x20,
+ 0x4A, 0x44, 0x91, 0xDF, 0x1C, 0xFE, 0x86, 0x28,
+ 0x12, 0x2D, 0x66, 0xDF, 0xBE, 0xAD, 0x96, 0x61,
+ 0xED, 0xF2, 0xF7, 0x41, 0x7B, 0x57, 0x88, 0x6B,
+ 0x24, 0x1E, 0x7D, 0xEC, 0xBE, 0x98, 0x65, 0x65,
+ 0x36, 0x65, 0x99, 0xA9, 0xFE, 0x24, 0x67, 0x85,
+ 0x99, 0xEE, 0x2A, 0xAE, 0xEE, 0xB1, 0x81, 0x1A,
+ 0x22, 0xE3, 0x6D, 0x75, 0x6E, 0x21, 0xBC, 0xEF,
+ 0x11, 0x5C, 0x61, 0xAF, 0x0C, 0x30, 0x00, 0xB6,
+ 0xA2, 0x23, 0xED, 0xFE, 0x70, 0x15, 0xDA, 0x52,
+ 0xE1, 0xE6, 0x2D, 0xCE, 0x34, 0xE8, 0xAA, 0x4C,
+ 0xF1, 0xD6, 0x67, 0x56, 0x57, 0xD3, 0xDB, 0xC0,
+ 0x90, 0x49, 0x6F, 0x45, 0x73, 0x93, 0x4E, 0x30,
+ 0x30, 0x70, 0xF5, 0xC9, 0x8F, 0x31, 0x25, 0xF2,
+ 0xC2, 0xE7, 0x33, 0x7F, 0x4E, 0xB6, 0xF5, 0x2A,
+ 0xDF, 0x20, 0x00, 0xE5, 0x79, 0xB2, 0xD0, 0xF9,
+ 0x17, 0xF7, 0x7E, 0x16, 0x90, 0x40, 0x00, 0x57,
+ 0x91, 0x44, 0x78, 0xEF, 0x1C, 0xE0, 0x85, 0x09,
+ 0xDA, 0xF4, 0x14, 0x7E, 0x4B, 0xD7, 0x35, 0xD6,
+ 0x87, 0x54, 0x8F, 0x2A, 0xB5, 0xA7, 0x6F, 0x50,
+ 0xD0, 0xF7, 0xD1, 0xF1, 0x19, 0xC9, 0xAC, 0x22,
+ 0x7E, 0x05, 0x11, 0xF5, 0xF2, 0x6D, 0xEE, 0x92,
+ 0x27, 0x57, 0x5F, 0xE5, 0x15, 0x0D, 0x27, 0x68,
+ 0xBF, 0x52, 0x65, 0x74, 0x73, 0xA6, 0x58, 0x6D,
+ 0x79, 0x18, 0xAC, 0x31, 0xDD, 0xDD, 0x80, 0x8B,
+ 0x75, 0x24, 0xE1, 0x17, 0xE1, 0x95, 0x25, 0x16,
+ 0x29, 0xAB, 0x69, 0x69, 0xC8, 0x28, 0xEE, 0x5D
+};
+
+static const unsigned char Dummy_rsa_privExp[256] = //Dummy_rsa_privExp
+{
+ 0xE3, 0xC6, 0x76, 0x57, 0x2E, 0xCB, 0xA5, 0xE6,
+ 0x0C, 0x01, 0xBD, 0x5C, 0x32, 0x2D, 0x90, 0xE0,
+ 0xFF, 0x9A, 0x80, 0xE8, 0x66, 0x8D, 0x84, 0xDC,
+ 0xF7, 0x75, 0x5F, 0x3F, 0x98, 0x7C, 0x97, 0x40,
+ 0x20, 0x21, 0xB7, 0x24, 0xC0, 0x61, 0x2D, 0x83,
+ 0xB0, 0x91, 0x8E, 0xE3, 0xC2, 0xD0, 0x2C, 0xA1,
+ 0x2C, 0x99, 0x4F, 0x48, 0xF7, 0x4E, 0x13, 0xD3,
+ 0x01, 0x71, 0x25, 0x9B, 0x3C, 0x75, 0x7C, 0xC4,
+ 0xE5, 0x89, 0x7E, 0xDA, 0xF9, 0x99, 0x5C, 0x83,
+ 0xE4, 0xDD, 0x36, 0x62, 0x5B, 0x0E, 0x12, 0x91,
+ 0xD6, 0x39, 0x45, 0x69, 0x62, 0x20, 0xCA, 0xF4,
+ 0xBA, 0x6B, 0x28, 0x1A, 0x7C, 0xBF, 0xB9, 0x97,
+ 0x37, 0x46, 0xC2, 0x7A, 0xCF, 0x10, 0x68, 0xC2,
+ 0xC9, 0xF1, 0x48, 0xDA, 0x8A, 0x2F, 0x4C, 0xBC,
+ 0x3B, 0x1C, 0xB8, 0x8F, 0x04, 0x7F, 0xFD, 0x9D,
+ 0xE2, 0x0A, 0xD2, 0x09, 0x39, 0xC7, 0xD9, 0x81,
+ 0x59, 0x17, 0x73, 0xB2, 0xEC, 0xEB, 0x36, 0x67,
+ 0xA5, 0xA8, 0xD5, 0x71, 0xD9, 0x38, 0x6A, 0xD1,
+ 0x28, 0xB9, 0x46, 0x85, 0x3A, 0x81, 0x85, 0x4E,
+ 0x55, 0xA7, 0x74, 0x79, 0xBB, 0xC5, 0x97, 0xF7,
+ 0xEF, 0xE0, 0x81, 0x20, 0xE0, 0xEA, 0x45, 0x8F,
+ 0xED, 0x70, 0x8E, 0xD6, 0xFF, 0x49, 0xCF, 0x7F,
+ 0xF2, 0xFF, 0x22, 0x20, 0x3F, 0xE9, 0x92, 0x99,
+ 0xDE, 0x81, 0xD6, 0x27, 0xF7, 0xB8, 0x3A, 0x1D,
+ 0x4F, 0xA2, 0x50, 0xFB, 0xA5, 0xE7, 0x98, 0x08,
+ 0xB5, 0x2B, 0xA2, 0x94, 0xA9, 0x17, 0x1A, 0xA8,
+ 0x34, 0xF6, 0x5E, 0x24, 0x2D, 0x40, 0x2F, 0xCB,
+ 0x3C, 0xB0, 0xF8, 0x7E, 0x84, 0xB4, 0x87, 0x82,
+ 0x19, 0xAF, 0x87, 0xB6, 0xFA, 0xA9, 0x67, 0x27,
+ 0x07, 0x28, 0xBA, 0x2E, 0xA5, 0x8E, 0xDD, 0xE5,
+ 0xD4, 0xFD, 0x06, 0x09, 0xDF, 0xBD, 0x87, 0x95,
+ 0x95, 0x25, 0x05, 0x5E, 0xB2, 0x00, 0x18, 0x41
+};
+
+static const unsigned char Dummy_rsa_pubMod[256] = //Dummy_rsa_pubMod
+{
+ 0xE6, 0x64, 0x06, 0x6C, 0x49, 0x6B, 0xEC, 0xEE,
+ 0x59, 0xAE, 0x11, 0x92, 0xF1, 0x03, 0x43, 0x87,
+ 0x8E, 0xEB, 0x4D, 0x70, 0xA9, 0x71, 0xB4, 0x6D,
+ 0x25, 0x19, 0x02, 0x4A, 0x9E, 0x4D, 0xA3, 0x10,
+ 0xFD, 0xB2, 0x27, 0x56, 0xA3, 0xFB, 0xDD, 0xE5,
+ 0xE4, 0x4E, 0xE0, 0x62, 0x8F, 0xC3, 0x2E, 0xEE,
+ 0x8F, 0x9D, 0x4D, 0x6E, 0x00, 0xDB, 0x88, 0x49,
+ 0xA2, 0xFC, 0x30, 0xFE, 0x94, 0xF3, 0x06, 0x92,
+ 0x75, 0x61, 0x11, 0x1D, 0x24, 0x07, 0xE9, 0x12,
+ 0xB6, 0xB1, 0x57, 0xF5, 0xDC, 0x01, 0xF7, 0x54,
+ 0xBF, 0xC3, 0xAC, 0x8C, 0x73, 0x2C, 0x73, 0x17,
+ 0x8E, 0xBF, 0x2F, 0x68, 0x3C, 0x61, 0x75, 0x32,
+ 0x15, 0x39, 0x93, 0xDD, 0xBA, 0x12, 0x42, 0xD3,
+ 0x25, 0x85, 0xFA, 0xA6, 0x4B, 0xAF, 0x81, 0x4B,
+ 0xCA, 0xD2, 0x9C, 0xF1, 0x3D, 0x37, 0xAE, 0xB9,
+ 0xFD, 0x77, 0x59, 0x78, 0xB9, 0x32, 0x95, 0x19,
+ 0xD1, 0x47, 0xE1, 0xC6, 0xE1, 0x16, 0x13, 0x5D,
+ 0xCC, 0x99, 0x31, 0x63, 0xAD, 0xBB, 0xA5, 0x4F,
+ 0xE4, 0x41, 0x67, 0xFD, 0x7F, 0x1E, 0xA8, 0x9A,
+ 0x35, 0x65, 0xEB, 0xC4, 0x4D, 0xD4, 0xC4, 0x29,
+ 0x0F, 0x40, 0x95, 0xFD, 0x8A, 0x30, 0x67, 0x79,
+ 0xFB, 0xD4, 0x76, 0x6F, 0xD1, 0xDE, 0x8C, 0x72,
+ 0x32, 0x05, 0x97, 0x5A, 0x26, 0x0D, 0x37, 0xCA,
+ 0x12, 0x2C, 0xDC, 0x14, 0x3F, 0xD3, 0x59, 0x00,
+ 0x66, 0xD2, 0x8E, 0xF5, 0x6E, 0x22, 0x08, 0x63,
+ 0x59, 0xB5, 0x3F, 0xBB, 0x3A, 0x4D, 0xD4, 0xD1,
+ 0xC1, 0x21, 0xA7, 0x4D, 0x02, 0x96, 0x08, 0xF5,
+ 0x2B, 0x11, 0xE5, 0x85, 0xD2, 0x6E, 0x91, 0xD6,
+ 0x8F, 0x77, 0x72, 0xEF, 0x37, 0xE3, 0x79, 0x19,
+ 0xA9, 0xEE, 0x58, 0x5D, 0x52, 0x9B, 0x2D, 0x47,
+ 0x7D, 0x27, 0xB8, 0xC3, 0x76, 0xCA, 0xDA, 0xC2,
+ 0xF4, 0xFC, 0xF4, 0x53, 0x7C, 0xD8, 0x43, 0x87
+};
+
+//Certificates
+static const unsigned char ca3_dpki_cert[0x400] =
+{
+ 0x00, 0x01, 0x00, 0x03, 0x70, 0x41, 0x38, 0xEF,
+ 0xBB, 0xBD, 0xA1, 0x6A, 0x98, 0x7D, 0xD9, 0x01,
+ 0x32, 0x6D, 0x1C, 0x94, 0x59, 0x48, 0x4C, 0x88,
+ 0xA2, 0x86, 0x1B, 0x91, 0xA3, 0x12, 0x58, 0x7A,
+ 0xE7, 0x0E, 0xF6, 0x23, 0x7E, 0xC5, 0x0E, 0x10,
+ 0x32, 0xDC, 0x39, 0xDD, 0xE8, 0x9A, 0x96, 0xA8,
+ 0xE8, 0x59, 0xD7, 0x6A, 0x98, 0xA6, 0xE7, 0xE3,
+ 0x6A, 0x0C, 0xFE, 0x35, 0x2C, 0xA8, 0x93, 0x05,
+ 0x82, 0x34, 0xFF, 0x83, 0x3F, 0xCB, 0x3B, 0x03,
+ 0x81, 0x1E, 0x9F, 0x0D, 0xC0, 0xD9, 0xA5, 0x2F,
+ 0x80, 0x45, 0xB4, 0xB2, 0xF9, 0x41, 0x1B, 0x67,
+ 0xA5, 0x1C, 0x44, 0xB5, 0xEF, 0x8C, 0xE7, 0x7B,
+ 0xD6, 0xD5, 0x6B, 0xA7, 0x57, 0x34, 0xA1, 0x85,
+ 0x6D, 0xE6, 0xD4, 0xBE, 0xD6, 0xD3, 0xA2, 0x42,
+ 0xC7, 0xC8, 0x79, 0x1B, 0x34, 0x22, 0x37, 0x5E,
+ 0x5C, 0x77, 0x9A, 0xBF, 0x07, 0x2F, 0x76, 0x95,
+ 0xEF, 0xA0, 0xF7, 0x5B, 0xCB, 0x83, 0x78, 0x9F,
+ 0xC3, 0x0E, 0x3F, 0xE4, 0xCC, 0x83, 0x92, 0x20,
+ 0x78, 0x40, 0x63, 0x89, 0x49, 0xC7, 0xF6, 0x88,
+ 0x56, 0x5F, 0x64, 0x9B, 0x74, 0xD6, 0x3D, 0x8D,
+ 0x58, 0xFF, 0xAD, 0xDA, 0x57, 0x1E, 0x95, 0x54,
+ 0x42, 0x6B, 0x13, 0x18, 0xFC, 0x46, 0x89, 0x83,
+ 0xD4, 0xC8, 0xA5, 0x62, 0x8B, 0x06, 0xB6, 0xFC,
+ 0x5D, 0x50, 0x7C, 0x13, 0xE7, 0xA1, 0x8A, 0xC1,
+ 0x51, 0x1E, 0xB6, 0xD6, 0x2E, 0xA5, 0x44, 0x8F,
+ 0x83, 0x50, 0x14, 0x47, 0xA9, 0xAF, 0xB3, 0xEC,
+ 0xC2, 0x90, 0x3C, 0x9D, 0xD5, 0x2F, 0x92, 0x2A,
+ 0xC9, 0xAC, 0xDB, 0xEF, 0x58, 0xC6, 0x02, 0x18,
+ 0x48, 0xD9, 0x6E, 0x20, 0x87, 0x32, 0xD3, 0xD1,
+ 0xD9, 0xD9, 0xEA, 0x44, 0x0D, 0x91, 0x62, 0x1C,
+ 0x7A, 0x99, 0xDB, 0x88, 0x43, 0xC5, 0x9C, 0x1F,
+ 0x2E, 0x2C, 0x7D, 0x9B, 0x57, 0x7D, 0x51, 0x2C,
+ 0x16, 0x6D, 0x6F, 0x7E, 0x1A, 0xAD, 0x4A, 0x77,
+ 0x4A, 0x37, 0x44, 0x7E, 0x78, 0xFE, 0x20, 0x21,
+ 0xE1, 0x4A, 0x95, 0xD1, 0x12, 0xA0, 0x68, 0xAD,
+ 0xA0, 0x19, 0xF4, 0x63, 0xC7, 0xA5, 0x56, 0x85,
+ 0xAA, 0xBB, 0x68, 0x88, 0xB9, 0x24, 0x64, 0x83,
+ 0xD1, 0x8B, 0x9C, 0x80, 0x6F, 0x47, 0x49, 0x18,
+ 0x33, 0x17, 0x82, 0x34, 0x4A, 0x4B, 0x85, 0x31,
+ 0x33, 0x4B, 0x26, 0x30, 0x32, 0x63, 0xD9, 0xD2,
+ 0xEB, 0x4F, 0x4B, 0xB9, 0x96, 0x02, 0xB3, 0x52,
+ 0xF6, 0xAE, 0x40, 0x46, 0xC6, 0x9A, 0x5E, 0x7E,
+ 0x8E, 0x4A, 0x18, 0xEF, 0x9B, 0xC0, 0xA2, 0xDE,
+ 0xD6, 0x13, 0x10, 0x41, 0x70, 0x12, 0xFD, 0x82,
+ 0x4C, 0xC1, 0x16, 0xCF, 0xB7, 0xC4, 0xC1, 0xF7,
+ 0xEC, 0x71, 0x77, 0xA1, 0x74, 0x46, 0xCB, 0xDE,
+ 0x96, 0xF3, 0xED, 0xD8, 0x8F, 0xCD, 0x05, 0x2F,
+ 0x0B, 0x88, 0x8A, 0x45, 0xFD, 0xAF, 0x2B, 0x63,
+ 0x13, 0x54, 0xF4, 0x0D, 0x16, 0xE5, 0xFA, 0x9C,
+ 0x2C, 0x4E, 0xDA, 0x98, 0xE7, 0x98, 0xD1, 0x5E,
+ 0x60, 0x46, 0xDC, 0x53, 0x63, 0xF3, 0x09, 0x6B,
+ 0x2C, 0x60, 0x7A, 0x9D, 0x8D, 0xD5, 0x5B, 0x15,
+ 0x02, 0xA6, 0xAC, 0x7D, 0x3C, 0xC8, 0xD8, 0xC5,
+ 0x75, 0x99, 0x8E, 0x7D, 0x79, 0x69, 0x10, 0xC8,
+ 0x04, 0xC4, 0x95, 0x23, 0x50, 0x57, 0xE9, 0x1E,
+ 0xCD, 0x26, 0x37, 0xC9, 0xC1, 0x84, 0x51, 0x51,
+ 0xAC, 0x6B, 0x9A, 0x04, 0x90, 0xAE, 0x3E, 0xC6,
+ 0xF4, 0x77, 0x40, 0xA0, 0xDB, 0x0B, 0xA3, 0x6D,
+ 0x07, 0x59, 0x56, 0xCE, 0xE7, 0x35, 0x4E, 0xA3,
+ 0xE9, 0xA4, 0xF2, 0x72, 0x0B, 0x26, 0x55, 0x0C,
+ 0x7D, 0x39, 0x43, 0x24, 0xBC, 0x0C, 0xB7, 0xE9,
+ 0x31, 0x7D, 0x8A, 0x86, 0x61, 0xF4, 0x21, 0x91,
+ 0xFF, 0x10, 0xB0, 0x82, 0x56, 0xCE, 0x3F, 0xD2,
+ 0x5B, 0x74, 0x5E, 0x51, 0x94, 0x90, 0x6B, 0x4D,
+ 0x61, 0xCB, 0x4C, 0x2E, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x52, 0x6F, 0x6F, 0x74, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x43, 0x41, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0xE8, 0xEF, 0x6C,
+ 0xB2, 0x79, 0xC9, 0xE2, 0xEE, 0xE1, 0x21, 0xC6,
+ 0xEA, 0xF4, 0x4F, 0xF6, 0x39, 0xF8, 0x8F, 0x07,
+ 0x8B, 0x4B, 0x77, 0xED, 0x9F, 0x95, 0x60, 0xB0,
+ 0x35, 0x82, 0x81, 0xB5, 0x0E, 0x55, 0xAB, 0x72,
+ 0x11, 0x15, 0xA1, 0x77, 0x70, 0x3C, 0x7A, 0x30,
+ 0xFE, 0x3A, 0xE9, 0xEF, 0x1C, 0x60, 0xBC, 0x1D,
+ 0x97, 0x46, 0x76, 0xB2, 0x3A, 0x68, 0xCC, 0x04,
+ 0xB1, 0x98, 0x52, 0x5B, 0xC9, 0x68, 0xF1, 0x1D,
+ 0xE2, 0xDB, 0x50, 0xE4, 0xD9, 0xE7, 0xF0, 0x71,
+ 0xE5, 0x62, 0xDA, 0xE2, 0x09, 0x22, 0x33, 0xE9,
+ 0xD3, 0x63, 0xF6, 0x1D, 0xD7, 0xC1, 0x9F, 0xF3,
+ 0xA4, 0xA9, 0x1E, 0x8F, 0x65, 0x53, 0xD4, 0x71,
+ 0xDD, 0x7B, 0x84, 0xB9, 0xF1, 0xB8, 0xCE, 0x73,
+ 0x35, 0xF0, 0xF5, 0x54, 0x05, 0x63, 0xA1, 0xEA,
+ 0xB8, 0x39, 0x63, 0xE0, 0x9B, 0xE9, 0x01, 0x01,
+ 0x1F, 0x99, 0x54, 0x63, 0x61, 0x28, 0x70, 0x20,
+ 0xE9, 0xCC, 0x0D, 0xAB, 0x48, 0x7F, 0x14, 0x0D,
+ 0x66, 0x26, 0xA1, 0x83, 0x6D, 0x27, 0x11, 0x1F,
+ 0x20, 0x68, 0xDE, 0x47, 0x72, 0x14, 0x91, 0x51,
+ 0xCF, 0x69, 0xC6, 0x1B, 0xA6, 0x0E, 0xF9, 0xD9,
+ 0x49, 0xA0, 0xF7, 0x1F, 0x54, 0x99, 0xF2, 0xD3,
+ 0x9A, 0xD2, 0x8C, 0x70, 0x05, 0x34, 0x82, 0x93,
+ 0xC4, 0x31, 0xFF, 0xBD, 0x33, 0xF6, 0xBC, 0xA6,
+ 0x0D, 0xC7, 0x19, 0x5E, 0xA2, 0xBC, 0xC5, 0x6D,
+ 0x20, 0x0B, 0xAF, 0x6D, 0x06, 0xD0, 0x9C, 0x41,
+ 0xDB, 0x8D, 0xE9, 0xC7, 0x20, 0x15, 0x4C, 0xA4,
+ 0x83, 0x2B, 0x69, 0xC0, 0x8C, 0x69, 0xCD, 0x3B,
+ 0x07, 0x3A, 0x00, 0x63, 0x60, 0x2F, 0x46, 0x2D,
+ 0x33, 0x80, 0x61, 0xA5, 0xEA, 0x6C, 0x91, 0x5C,
+ 0xD5, 0x62, 0x35, 0x79, 0xC3, 0xEB, 0x64, 0xCE,
+ 0x44, 0xEF, 0x58, 0x6D, 0x14, 0xBA, 0xAA, 0x88,
+ 0x34, 0x01, 0x9B, 0x3E, 0xEB, 0xEE, 0xD3, 0x79,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char xsC_dpki_cert[0x300] =
+{
+ 0x00, 0x01, 0x00, 0x04, 0x91, 0x9E, 0xBE, 0x46,
+ 0x4A, 0xD0, 0xF5, 0x52, 0xCD, 0x1B, 0x72, 0xE7,
+ 0x88, 0x49, 0x10, 0xCF, 0x55, 0xA9, 0xF0, 0x2E,
+ 0x50, 0x78, 0x96, 0x41, 0xD8, 0x96, 0x68, 0x3D,
+ 0xC0, 0x05, 0xBD, 0x0A, 0xEA, 0x87, 0x07, 0x9D,
+ 0x8A, 0xC2, 0x84, 0xC6, 0x75, 0x06, 0x5F, 0x74,
+ 0xC8, 0xBF, 0x37, 0xC8, 0x80, 0x44, 0x40, 0x95,
+ 0x02, 0xA0, 0x22, 0x98, 0x0B, 0xB8, 0xAD, 0x48,
+ 0x38, 0x3F, 0x6D, 0x28, 0xA7, 0x9D, 0xE3, 0x96,
+ 0x26, 0xCC, 0xB2, 0xB2, 0x2A, 0x0F, 0x19, 0xE4,
+ 0x10, 0x32, 0xF0, 0x94, 0xB3, 0x9F, 0xF0, 0x13,
+ 0x31, 0x46, 0xDE, 0xC8, 0xF6, 0xC1, 0xA9, 0xD5,
+ 0x5C, 0xD2, 0x8D, 0x9E, 0x1C, 0x47, 0xB3, 0xD1,
+ 0x1F, 0x4F, 0x54, 0x26, 0xC2, 0xC7, 0x80, 0x13,
+ 0x5A, 0x27, 0x75, 0xD3, 0xCA, 0x67, 0x9B, 0xC7,
+ 0xE8, 0x34, 0xF0, 0xE0, 0xFB, 0x58, 0xE6, 0x88,
+ 0x60, 0xA7, 0x13, 0x30, 0xFC, 0x95, 0x79, 0x17,
+ 0x93, 0xC8, 0xFB, 0xA9, 0x35, 0xA7, 0xA6, 0x90,
+ 0x8F, 0x22, 0x9D, 0xEE, 0x2A, 0x0C, 0xA6, 0xB9,
+ 0xB2, 0x3B, 0x12, 0xD4, 0x95, 0xA6, 0xFE, 0x19,
+ 0xD0, 0xD7, 0x26, 0x48, 0x21, 0x68, 0x78, 0x60,
+ 0x5A, 0x66, 0x53, 0x8D, 0xBF, 0x37, 0x68, 0x99,
+ 0x90, 0x5D, 0x34, 0x45, 0xFC, 0x5C, 0x72, 0x7A,
+ 0x0E, 0x13, 0xE0, 0xE2, 0xC8, 0x97, 0x1C, 0x9C,
+ 0xFA, 0x6C, 0x60, 0x67, 0x88, 0x75, 0x73, 0x2A,
+ 0x4E, 0x75, 0x52, 0x3D, 0x2F, 0x56, 0x2F, 0x12,
+ 0xAA, 0xBD, 0x15, 0x73, 0xBF, 0x06, 0xC9, 0x40,
+ 0x54, 0xAE, 0xFA, 0x81, 0xA7, 0x14, 0x17, 0xAF,
+ 0x9A, 0x4A, 0x06, 0x6D, 0x0F, 0xFC, 0x5A, 0xD6,
+ 0x4B, 0xAB, 0x28, 0xB1, 0xFF, 0x60, 0x66, 0x1F,
+ 0x44, 0x37, 0xD4, 0x9E, 0x1E, 0x0D, 0x94, 0x12,
+ 0xEB, 0x4B, 0xCA, 0xCF, 0x4C, 0xFD, 0x6A, 0x34,
+ 0x08, 0x84, 0x79, 0x82, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x43, 0x41, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x58, 0x53, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x63, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x13, 0x7A, 0x08, 0x94,
+ 0xAD, 0x50, 0x5B, 0xB6, 0xC6, 0x7E, 0x2E, 0x5B,
+ 0xDD, 0x6A, 0x3B, 0xEC, 0x43, 0xD9, 0x10, 0xC7,
+ 0x72, 0xE9, 0xCC, 0x29, 0x0D, 0xA5, 0x85, 0x88,
+ 0xB7, 0x7D, 0xCC, 0x11, 0x68, 0x0B, 0xB3, 0xE2,
+ 0x9F, 0x4E, 0xAB, 0xBB, 0x26, 0xE9, 0x8C, 0x26,
+ 0x01, 0x98, 0x5C, 0x04, 0x1B, 0xB1, 0x43, 0x78,
+ 0xE6, 0x89, 0x18, 0x1A, 0xAD, 0x77, 0x05, 0x68,
+ 0xE9, 0x28, 0xA2, 0xB9, 0x81, 0x67, 0xEE, 0x3E,
+ 0x10, 0xD0, 0x72, 0xBE, 0xEF, 0x1F, 0xA2, 0x2F,
+ 0xA2, 0xAA, 0x3E, 0x13, 0xF1, 0x1E, 0x18, 0x36,
+ 0xA9, 0x2A, 0x42, 0x81, 0xEF, 0x70, 0xAA, 0xF4,
+ 0xE4, 0x62, 0x99, 0x82, 0x21, 0xC6, 0xFB, 0xB9,
+ 0xBD, 0xD0, 0x17, 0xE6, 0xAC, 0x59, 0x04, 0x94,
+ 0xE9, 0xCE, 0xA9, 0x85, 0x9C, 0xEB, 0x2D, 0x2A,
+ 0x4C, 0x17, 0x66, 0xF2, 0xC3, 0x39, 0x12, 0xC5,
+ 0x8F, 0x14, 0xA8, 0x03, 0xE3, 0x6F, 0xCC, 0xDC,
+ 0xCC, 0xDC, 0x13, 0xFD, 0x7A, 0xE7, 0x7C, 0x7A,
+ 0x78, 0xD9, 0x97, 0xE6, 0xAC, 0xC3, 0x55, 0x57,
+ 0xE0, 0xD3, 0xE9, 0xEB, 0x64, 0xB4, 0x3C, 0x92,
+ 0xF4, 0xC5, 0x0D, 0x67, 0xA6, 0x02, 0xDE, 0xB3,
+ 0x91, 0xB0, 0x66, 0x61, 0xCD, 0x32, 0x88, 0x0B,
+ 0xD6, 0x49, 0x12, 0xAF, 0x1C, 0xBC, 0xB7, 0x16,
+ 0x2A, 0x06, 0xF0, 0x25, 0x65, 0xD3, 0xB0, 0xEC,
+ 0xE4, 0xFC, 0xEC, 0xDD, 0xAE, 0x8A, 0x49, 0x34,
+ 0xDB, 0x8E, 0xE6, 0x7F, 0x30, 0x17, 0x98, 0x62,
+ 0x21, 0x15, 0x5D, 0x13, 0x1C, 0x6C, 0x3F, 0x09,
+ 0xAB, 0x19, 0x45, 0xC2, 0x06, 0xAC, 0x70, 0xC9,
+ 0x42, 0xB3, 0x6F, 0x49, 0xA1, 0x18, 0x3B, 0xCD,
+ 0x78, 0xB6, 0xE4, 0xB4, 0x7C, 0x6C, 0x5C, 0xAC,
+ 0x0F, 0x8D, 0x62, 0xF8, 0x97, 0xC6, 0x95, 0x3D,
+ 0xD1, 0x2F, 0x28, 0xB7, 0x0C, 0x5B, 0x7D, 0xF7,
+ 0x51, 0x81, 0x9A, 0x98, 0x34, 0x65, 0x26, 0x25,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char cpB_dpki_cert[0x300] =
+{
+ 0x00, 0x01, 0x00, 0x04, 0x2E, 0xA6, 0x6C, 0x66,
+ 0xCF, 0xF3, 0x35, 0x79, 0x7D, 0x04, 0x97, 0xB7,
+ 0x7A, 0x19, 0x7F, 0x9F, 0xE5, 0x1A, 0xB5, 0xA4,
+ 0x13, 0x75, 0xDC, 0x73, 0xFD, 0x9E, 0x0B, 0x10,
+ 0x66, 0x9B, 0x1B, 0x9A, 0x5B, 0x7E, 0x8A, 0xB2,
+ 0x8F, 0x01, 0xB6, 0x7B, 0x62, 0x54, 0xC1, 0x4A,
+ 0xA1, 0x33, 0x14, 0x18, 0xF2, 0x5B, 0xA5, 0x49,
+ 0x00, 0x4C, 0x37, 0x8D, 0xD7, 0x2F, 0x0C, 0xE6,
+ 0x3B, 0x1F, 0x70, 0x91, 0xAA, 0xFE, 0x38, 0x09,
+ 0xB7, 0xAC, 0x6C, 0x28, 0x76, 0xA6, 0x1D, 0x60,
+ 0x51, 0x6C, 0x43, 0xA6, 0x37, 0x29, 0x16, 0x2D,
+ 0x28, 0x0B, 0xE2, 0x1B, 0xE8, 0xE2, 0xFE, 0x05,
+ 0x7D, 0x8E, 0xB6, 0xE2, 0x04, 0x24, 0x22, 0x45,
+ 0x73, 0x1A, 0xB6, 0xFE, 0xE3, 0x0E, 0x53, 0x35,
+ 0x37, 0x3E, 0xEB, 0xA9, 0x70, 0xD5, 0x31, 0xBB,
+ 0xA2, 0xCB, 0x22, 0x2D, 0x96, 0x84, 0x38, 0x7D,
+ 0x5F, 0x2A, 0x1B, 0xF7, 0x52, 0x00, 0xCE, 0x06,
+ 0x56, 0xE3, 0x90, 0xCE, 0x19, 0x13, 0x5B, 0x59,
+ 0xE1, 0x4F, 0x0F, 0xA5, 0xC1, 0x28, 0x1A, 0x73,
+ 0x86, 0xCC, 0xD1, 0xC8, 0xEC, 0x3F, 0xAD, 0x70,
+ 0xFB, 0xCE, 0x74, 0xDE, 0xEE, 0x1F, 0xD0, 0x5F,
+ 0x46, 0x33, 0x0B, 0x51, 0xF9, 0xB7, 0x9E, 0x1D,
+ 0xDB, 0xF4, 0xE3, 0x3F, 0x14, 0x88, 0x9D, 0x05,
+ 0x28, 0x29, 0x24, 0xC5, 0xF5, 0xDC, 0x27, 0x66,
+ 0xEF, 0x06, 0x27, 0xD7, 0xEE, 0xDC, 0x73, 0x6E,
+ 0x67, 0xC2, 0xE5, 0xB9, 0x38, 0x34, 0x66, 0x80,
+ 0x72, 0x21, 0x6D, 0x1C, 0x78, 0xB8, 0x23, 0xA0,
+ 0x72, 0xD3, 0x4F, 0xF3, 0xEC, 0xF9, 0xBD, 0x11,
+ 0xA2, 0x9A, 0xF1, 0x6C, 0x33, 0xBD, 0x09, 0xAF,
+ 0xB2, 0xD7, 0x4D, 0x53, 0x4E, 0x02, 0x7C, 0x19,
+ 0x24, 0x0D, 0x59, 0x5A, 0x68, 0xEB, 0xB3, 0x05,
+ 0xAC, 0xC4, 0x4A, 0xB3, 0x8A, 0xB8, 0x20, 0xC6,
+ 0xD4, 0x26, 0x56, 0x0C, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x43, 0x41, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x43, 0x50, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x62, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x13, 0x7A, 0x08, 0x0B,
+ 0xA6, 0x89, 0xC5, 0x90, 0xFD, 0x0B, 0x2F, 0x0D,
+ 0x4F, 0x56, 0xB6, 0x32, 0xFB, 0x93, 0x4E, 0xD0,
+ 0x73, 0x95, 0x17, 0xB3, 0x3A, 0x79, 0xDE, 0x04,
+ 0x0E, 0xE9, 0x2D, 0xC3, 0x1D, 0x37, 0xC7, 0xF7,
+ 0x3B, 0xF0, 0x4B, 0xD3, 0xE4, 0x4E, 0x20, 0xAB,
+ 0x5A, 0x6F, 0xEA, 0xF5, 0x98, 0x4C, 0xC1, 0xF6,
+ 0x06, 0x2E, 0x9A, 0x9F, 0xE5, 0x6C, 0x32, 0x85,
+ 0xDC, 0x6F, 0x25, 0xDD, 0xD5, 0xD0, 0xBF, 0x9F,
+ 0xE2, 0xEF, 0xE8, 0x35, 0xDF, 0x26, 0x34, 0xED,
+ 0x93, 0x7F, 0xAB, 0x02, 0x14, 0xD1, 0x04, 0x80,
+ 0x9C, 0xF7, 0x4B, 0x86, 0x0E, 0x6B, 0x04, 0x83,
+ 0xF4, 0xCD, 0x2D, 0xAB, 0x2A, 0x96, 0x02, 0xBC,
+ 0x56, 0xF0, 0xD6, 0xBD, 0x94, 0x6A, 0xED, 0x6E,
+ 0x0B, 0xE4, 0xF0, 0x8F, 0x26, 0x68, 0x6B, 0xD0,
+ 0x9E, 0xF7, 0xDB, 0x32, 0x5F, 0x82, 0xB1, 0x8F,
+ 0x6A, 0xF2, 0xED, 0x52, 0x5B, 0xFD, 0x82, 0x8B,
+ 0x65, 0x3F, 0xEE, 0x6E, 0xCE, 0x40, 0x0D, 0x5A,
+ 0x48, 0xFF, 0xE2, 0x2D, 0x53, 0x8B, 0xB5, 0x33,
+ 0x5B, 0x41, 0x53, 0x34, 0x2D, 0x43, 0x35, 0xAC,
+ 0xF5, 0x90, 0xD0, 0xD3, 0x0A, 0xE2, 0x04, 0x3C,
+ 0x7F, 0x5A, 0xD2, 0x14, 0xFC, 0x9C, 0x0F, 0xE6,
+ 0xFA, 0x40, 0xA5, 0xC8, 0x65, 0x06, 0xCA, 0x63,
+ 0x69, 0xBC, 0xEE, 0x44, 0xA3, 0x2D, 0x9E, 0x69,
+ 0x5C, 0xF0, 0x0B, 0x4F, 0xD7, 0x9A, 0xDB, 0x56,
+ 0x8D, 0x14, 0x9C, 0x20, 0x28, 0xA1, 0x4C, 0x9D,
+ 0x71, 0xB8, 0x50, 0xCA, 0x36, 0x5B, 0x37, 0xF7,
+ 0x0B, 0x65, 0x77, 0x91, 0xFC, 0x5D, 0x72, 0x8C,
+ 0x4E, 0x18, 0xFD, 0x22, 0x55, 0x7C, 0x40, 0x62,
+ 0xD7, 0x47, 0x71, 0x53, 0x3C, 0x70, 0x17, 0x9D,
+ 0x3D, 0xAE, 0x8F, 0x92, 0xB1, 0x17, 0xE4, 0x5C,
+ 0xB3, 0x32, 0xF3, 0xB3, 0xC2, 0xA2, 0x2E, 0x70,
+ 0x5C, 0xFE, 0xC6, 0x6F, 0x6D, 0xA3, 0x77, 0x2B,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+#endif
\ No newline at end of file
diff --git a/keyset.c b/keyset.c
new file mode 100644
index 0000000..db089bf
--- /dev/null
+++ b/keyset.c
@@ -0,0 +1,200 @@
+#include "lib.h"
+
+// Private Prototypes
+int SetRsaKeySet(u8 **PrivDest, u8 *PrivSource, u8 **PubDest, u8 *PubSource);
+int SetUnFixedKey(keys_struct *keys, u8 *UnFixedKey);
+
+int SetTIK_RsaKey(keys_struct *keys, u8 *PrivateExp, u8 *PublicMod);
+int SetTMD_RsaKey(keys_struct *keys, u8 *PrivateExp, u8 *PublicMod);
+int SetCFA_RsaKey(keys_struct *keys, u8 *PrivateExp, u8 *PublicMod);
+int SetCCI_RsaKey(keys_struct *keys, u8 *PrivateExp, u8 *PublicMod);
+int SetAccessDesc_RsaKey(keys_struct *keys, u8 *PrivateExp, u8 *PublicMod);
+int SetCXI_RsaKey(keys_struct *keys, u8 *PrivateExp, u8 *PublicMod);
+
+int SetCaCert(keys_struct *keys, u8 *Cert);
+int SetTikCert(keys_struct *keys, u8 *Cert);
+int SetTmdCert(keys_struct *keys, u8 *Cert);
+
+
+// Code
+void InitKeys(keys_struct *keys)
+{
+ memset(keys,0,sizeof(keys_struct));
+
+#ifdef RETAIL_FSIGN
+ /* AES Keys */
+ // CIA
+ SetCommonKey(keys,(u8*)zeros_fixed_aesKey,1);
+ SetCurrentCommonKey(keys,1);
+
+ // NCCH
+ keys->aes.NormalKey = (u8*)zeros_fixed_aesKey;
+ SetSystemFixedKey(keys,(u8*)zeros_fixed_aesKey);
+
+ /* RSA Keys */
+ // CIA
+ SetTIK_RsaKey(keys,(u8*)Dummy_rsa_privExp,(u8*)Dummy_rsa_pubMod);
+ SetTMD_RsaKey(keys,(u8*)Dummy_rsa_privExp,(u8*)Dummy_rsa_pubMod);
+ // CFA
+ SetCFA_RsaKey(keys,(u8*)Dummy_rsa_privExp,(u8*)Dummy_rsa_pubMod);
+ // CCI
+ SetCCI_RsaKey(keys,(u8*)Dummy_rsa_privExp,(u8*)Dummy_rsa_pubMod);
+ // CXI
+ SetAccessDesc_RsaKey(keys,(u8*)Dummy_rsa_privExp,(u8*)Dummy_rsa_pubMod);
+
+ /* Certs */
+ SetCaCert(keys,(u8*)ca3_dpki_cert);
+ SetTikCert(keys,(u8*)xsC_dpki_cert);
+ SetTmdCert(keys,(u8*)cpB_dpki_cert);
+#else // DEBUG KEYS
+ /* AES Keys */
+ // CIA
+ SetCommonKey(keys,(u8*)ctr_aes_common_key_dev0,0);
+ SetCommonKey(keys,(u8*)ctr_aes_common_key_dev1,1);
+ SetCurrentCommonKey(keys,0);
+
+ // NCCH
+ keys->aes.NormalKey = (u8*)zeros_fixed_aesKey;
+ SetSystemFixedKey(keys,(u8*)system_fixed_aesKey);
+
+ /* RSA Keys */
+ // CIA
+ SetTIK_RsaKey(keys,(u8*)xs9_dpki_rsa_privExp,(u8*)xs9_dpki_rsa_pubMod);
+ SetTMD_RsaKey(keys,(u8*)cpA_dpki_rsa_privExp,(u8*)cpA_dpki_rsa_pubMod);
+ // CFA
+ SetCFA_RsaKey(keys,(u8*)DevNcsdCfa_privExp,(u8*)DevNcsdCfa_pubMod);
+ // CCI
+ SetCCI_RsaKey(keys,(u8*)DevNcsdCfa_privExp,(u8*)DevNcsdCfa_pubMod);
+ // CXI
+ SetAccessDesc_RsaKey(keys,(u8*)AccessDesc_privExp,(u8*)AccessDesc_pubMod);
+
+ /* Certs */
+ SetCaCert(keys,(u8*)ca4_dpki_cert);
+ SetTikCert(keys,(u8*)xs9_dpki_cert);
+ SetTmdCert(keys,(u8*)cpA_dpki_cert);
+#endif
+}
+
+void FreeKeys(keys_struct *keys)
+{
+ // AES
+ if(keys->aes.CommonKey){
+ for(int i = 0; i < 256; i++){
+ free(keys->aes.CommonKey[i]);
+ }
+ }
+ free(keys->aes.CommonKey);
+ free(keys->aes.SystemFixedKey);
+ free(keys->aes.UnFixedKey);
+
+ // RSA
+ free(keys->rsa.TIK_Priv);
+ free(keys->rsa.TIK_Pub);
+ free(keys->rsa.TMD_Priv);
+ free(keys->rsa.TMD_Pub);
+
+ free(keys->rsa.CFA_Priv);
+ free(keys->rsa.CFA_Pub);
+
+ free(keys->rsa.CCI_Priv);
+ free(keys->rsa.CCI_Pub);
+
+ free(keys->rsa.AccessDesc_Priv);
+ free(keys->rsa.AccessDesc_Pub);
+
+ // Certs
+ free(keys->certs.ca_cert);
+ free(keys->certs.tik_cert);
+ free(keys->certs.tmd_cert);
+ memset(keys,0,sizeof(keys_struct));
+}
+
+int SetRsaKeySet(u8 **PrivDest, u8 *PrivSource, u8 **PubDest, u8 *PubSource)
+{
+ int result = 0;
+ if(PrivSource){
+ result = CopyData(PrivDest,PrivSource,0x100);
+ if(result) return result;
+ }
+ if(PubSource){
+ result = CopyData(PubDest,PubSource,0x100);
+ if(result) return result;
+ }
+ return 0;
+}
+
+int SetCommonKey(keys_struct *keys, u8 *CommonKey, u8 Index)
+{
+ if(!keys) return -1;
+ if(!keys->aes.CommonKey){
+ keys->aes.CommonKey = malloc(sizeof(u8*)*256);
+ memset(keys->aes.CommonKey,0,sizeof(u8*)*256);
+ }
+ return CopyData(&keys->aes.CommonKey[Index],CommonKey,16);
+}
+
+int SetCurrentCommonKey(keys_struct *keys, u8 Index)
+{
+ if(!keys) return -1;
+ keys->aes.CurrentCommonKey = Index;
+ return 0;
+}
+
+int SetSystemFixedKey(keys_struct *keys, u8 *SystemFixedKey)
+{
+ if(!keys) return -1;
+ return CopyData(&keys->aes.SystemFixedKey,SystemFixedKey,16);
+}
+
+int SetUnFixedKey(keys_struct *keys, u8 *UnFixedKey)
+{
+ if(!keys) return -1;
+ return CopyData(&keys->aes.UnFixedKey,UnFixedKey,16);
+}
+
+int SetTIK_RsaKey(keys_struct *keys, u8 *PrivateExp, u8 *PublicMod)
+{
+ if(!keys) return -1;
+ return SetRsaKeySet(&keys->rsa.TIK_Priv,PrivateExp,&keys->rsa.TIK_Pub,PublicMod);
+}
+
+int SetTMD_RsaKey(keys_struct *keys, u8 *PrivateExp, u8 *PublicMod)
+{
+ if(!keys) return -1;
+ return SetRsaKeySet(&keys->rsa.TMD_Priv,PrivateExp,&keys->rsa.TMD_Pub,PublicMod);
+}
+
+int SetCFA_RsaKey(keys_struct *keys, u8 *PrivateExp, u8 *PublicMod)
+{
+ if(!keys) return -1;
+ return SetRsaKeySet(&keys->rsa.CFA_Priv,PrivateExp,&keys->rsa.CFA_Pub,PublicMod);
+}
+
+int SetCCI_RsaKey(keys_struct *keys, u8 *PrivateExp, u8 *PublicMod)
+{
+ if(!keys) return -1;
+ return SetRsaKeySet(&keys->rsa.CCI_Priv,PrivateExp,&keys->rsa.CCI_Pub,PublicMod);
+}
+
+int SetAccessDesc_RsaKey(keys_struct *keys, u8 *PrivateExp, u8 *PublicMod)
+{
+ if(!keys) return -1;
+ return SetRsaKeySet(&keys->rsa.AccessDesc_Priv,PrivateExp,&keys->rsa.AccessDesc_Pub,PublicMod);
+}
+
+int SetCaCert(keys_struct *keys, u8 *Cert)
+{
+ if(!keys) return -1;
+ return CopyData(&keys->certs.ca_cert,Cert,0x400);
+}
+int SetTikCert(keys_struct *keys, u8 *Cert)
+{
+ if(!keys) return -1;
+ return CopyData(&keys->certs.tik_cert,Cert,0x300);
+}
+
+int SetTmdCert(keys_struct *keys, u8 *Cert)
+{
+ if(!keys) return -1;
+ return CopyData(&keys->certs.tmd_cert,Cert,0x400);
+}
\ No newline at end of file
diff --git a/keyset.h b/keyset.h
new file mode 100644
index 0000000..319a911
--- /dev/null
+++ b/keyset.h
@@ -0,0 +1,58 @@
+#ifndef _KEYSET_H_
+#define _KEYSET_H_
+
+// Structs
+
+typedef struct
+{
+ struct
+ {
+ // CIA
+ u8 **CommonKey;
+ u8 CurrentCommonKey;
+
+ // NCCH Keys
+ u8 *NormalKey;
+ u8 *SystemFixedKey;
+ u8 *UnFixedKey;
+ } aes;
+
+ struct
+ {
+ // CIA RSA
+ u8 *TMD_Priv;
+ u8 *TMD_Pub;
+ u8 *TIK_Priv;
+ u8 *TIK_Pub;
+
+ // CFA
+ u8 *CFA_Priv;
+ u8 *CFA_Pub;
+
+ // CCI
+ u8 *CCI_Priv;
+ u8 *CCI_Pub;
+
+ // CXI
+ u8 *AccessDesc_Priv;
+ u8 *AccessDesc_Pub;
+ } rsa;
+
+ struct
+ {
+ // CIA
+ u8 *ca_cert;
+ u8 *tik_cert;
+ u8 *tmd_cert;
+ } certs;
+} keys_struct;
+
+#endif
+
+// Public Prototypes
+void InitKeys(keys_struct *keys);
+void FreeKeys(keys_struct *keys);
+
+int SetCommonKey(keys_struct *keys, u8 *CommonKey, u8 Index);
+int SetCurrentCommonKey(keys_struct *keys, u8 Index);
+int SetSystemFixedKey(keys_struct *keys, u8 *SystemFixedKey);
diff --git a/lib.h b/lib.h
new file mode 100644
index 0000000..8fe882c
--- /dev/null
+++ b/lib.h
@@ -0,0 +1,40 @@
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef _WIN32
+ #include
+ #include
+ #include
+ //#include
+#else
+ #include
+ #include
+#endif
+
+
+#include "types.h"
+#include "utils.h"
+#include "crypto.h"
+#ifdef RETAIL_FSIGN
+#include "keys_retail.h"
+#else
+#include "keys_debug.h"
+#include "accessdesc_sig.h"
+#endif
+#include "keyset.h"
+#include "usersettings.h"
+#include "libyaml/yaml.h"
+#include "yaml_ctr.h"
+
+
diff --git a/libyaml/LICENSE b/libyaml/LICENSE
new file mode 100644
index 0000000..050ced2
--- /dev/null
+++ b/libyaml/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2006 Kirill Simonov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/libyaml/api.c b/libyaml/api.c
new file mode 100644
index 0000000..d2c13d3
--- /dev/null
+++ b/libyaml/api.c
@@ -0,0 +1,1391 @@
+#include "libyaml/yaml_private.h"
+
+/*
+ * Get the library titleVersion.
+ */
+
+YAML_DECLARE(const char *)
+yaml_get_titleVersion_string(void)
+{
+ return YAML_titleVersion_STRING;
+}
+
+/*
+ * Get the library titleVersion numbers.
+ */
+
+YAML_DECLARE(void)
+yaml_get_titleVersion(int *major, int *minor, int *patch)
+{
+ *major = YAML_titleVersion_MAJOR;
+ *minor = YAML_titleVersion_MINOR;
+ *patch = YAML_titleVersion_PATCH;
+}
+
+/*
+ * Allocate a dynamic memory block.
+ */
+
+YAML_DECLARE(void *)
+yaml_malloc(size_t size)
+{
+ return malloc(size ? size : 1);
+}
+
+/*
+ * Reallocate a dynamic memory block.
+ */
+
+YAML_DECLARE(void *)
+yaml_realloc(void *ptr, size_t size)
+{
+ return ptr ? realloc(ptr, size ? size : 1) : malloc(size ? size : 1);
+}
+
+/*
+ * Free a dynamic memory block.
+ */
+
+YAML_DECLARE(void)
+yaml_free(void *ptr)
+{
+ if (ptr) free(ptr);
+}
+
+/*
+ * Duplicate a string.
+ */
+
+YAML_DECLARE(yaml_char_t *)
+yaml_strdup(const yaml_char_t *str)
+{
+ if (!str)
+ return NULL;
+
+ return (yaml_char_t *)strdup((char *)str);
+}
+
+/*
+ * Extend a string.
+ */
+
+YAML_DECLARE(int)
+yaml_string_extend(yaml_char_t **start,
+ yaml_char_t **pointer, yaml_char_t **end)
+{
+ yaml_char_t *new_start = yaml_realloc(*start, (*end - *start)*2);
+
+ if (!new_start) return 0;
+
+ memset(new_start + (*end - *start), 0, *end - *start);
+
+ *pointer = new_start + (*pointer - *start);
+ *end = new_start + (*end - *start)*2;
+ *start = new_start;
+
+ return 1;
+}
+
+/*
+ * Append a string B to a string A.
+ */
+
+YAML_DECLARE(int)
+yaml_string_join(
+ yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
+ yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end)
+{
+ if (*b_start == *b_pointer)
+ return 1;
+
+ while (*a_end - *a_pointer <= *b_pointer - *b_start) {
+ if (!yaml_string_extend(a_start, a_pointer, a_end))
+ return 0;
+ }
+
+ memcpy(*a_pointer, *b_start, *b_pointer - *b_start);
+ *a_pointer += *b_pointer - *b_start;
+
+ return 1;
+}
+
+/*
+ * Extend a stack.
+ */
+
+YAML_DECLARE(int)
+yaml_stack_extend(void **start, void **top, void **end)
+{
+ void *new_start = yaml_realloc(*start, ((char *)*end - (char *)*start)*2);
+
+ if (!new_start) return 0;
+
+ *top = (char *)new_start + ((char *)*top - (char *)*start);
+ *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
+ *start = new_start;
+
+ return 1;
+}
+
+/*
+ * Extend or move a queue.
+ */
+
+YAML_DECLARE(int)
+yaml_queue_extend(void **start, void **head, void **tail, void **end)
+{
+ /* Check if we need to resize the queue. */
+
+ if (*start == *head && *tail == *end) {
+ void *new_start = yaml_realloc(*start,
+ ((char *)*end - (char *)*start)*2);
+
+ if (!new_start) return 0;
+
+ *head = (char *)new_start + ((char *)*head - (char *)*start);
+ *tail = (char *)new_start + ((char *)*tail - (char *)*start);
+ *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
+ *start = new_start;
+ }
+
+ /* Check if we need to move the queue at the beginning of the buffer. */
+
+ if (*tail == *end) {
+ if (*head != *tail) {
+ memmove(*start, *head, (char *)*tail - (char *)*head);
+ }
+ *tail = (char *)*tail - (char *)*head + (char *)*start;
+ *head = *start;
+ }
+
+ return 1;
+}
+
+
+/*
+ * Create a new parser object.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_initialize(yaml_parser_t *parser)
+{
+ assert(parser); /* Non-NULL parser object expected. */
+
+ memset(parser, 0, sizeof(yaml_parser_t));
+ if (!BUFFER_INIT(parser, parser->raw_buffer, INPUT_RAW_BUFFER_SIZE))
+ goto error;
+ if (!BUFFER_INIT(parser, parser->buffer, INPUT_BUFFER_SIZE))
+ goto error;
+ if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE))
+ goto error;
+ if (!STACK_INIT(parser, parser->indents, INITIAL_STACK_SIZE))
+ goto error;
+ if (!STACK_INIT(parser, parser->simple_keys, INITIAL_STACK_SIZE))
+ goto error;
+ if (!STACK_INIT(parser, parser->states, INITIAL_STACK_SIZE))
+ goto error;
+ if (!STACK_INIT(parser, parser->marks, INITIAL_STACK_SIZE))
+ goto error;
+ if (!STACK_INIT(parser, parser->tag_directives, INITIAL_STACK_SIZE))
+ goto error;
+
+ return 1;
+
+error:
+
+ BUFFER_DEL(parser, parser->raw_buffer);
+ BUFFER_DEL(parser, parser->buffer);
+ QUEUE_DEL(parser, parser->tokens);
+ STACK_DEL(parser, parser->indents);
+ STACK_DEL(parser, parser->simple_keys);
+ STACK_DEL(parser, parser->states);
+ STACK_DEL(parser, parser->marks);
+ STACK_DEL(parser, parser->tag_directives);
+
+ return 0;
+}
+
+/*
+ * Destroy a parser object.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_delete(yaml_parser_t *parser)
+{
+ assert(parser); /* Non-NULL parser object expected. */
+
+ BUFFER_DEL(parser, parser->raw_buffer);
+ BUFFER_DEL(parser, parser->buffer);
+ while (!QUEUE_EMPTY(parser, parser->tokens)) {
+ yaml_token_delete(&DEQUEUE(parser, parser->tokens));
+ }
+ QUEUE_DEL(parser, parser->tokens);
+ STACK_DEL(parser, parser->indents);
+ STACK_DEL(parser, parser->simple_keys);
+ STACK_DEL(parser, parser->states);
+ STACK_DEL(parser, parser->marks);
+ while (!STACK_EMPTY(parser, parser->tag_directives)) {
+ yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
+ yaml_free(tag_directive.handle);
+ yaml_free(tag_directive.prefix);
+ }
+ STACK_DEL(parser, parser->tag_directives);
+
+ memset(parser, 0, sizeof(yaml_parser_t));
+}
+
+/*
+ * String read handler.
+ */
+
+static int
+yaml_string_read_handler(void *data, unsigned char *buffer, size_t size,
+ size_t *size_read)
+{
+ yaml_parser_t *parser = data;
+
+ if (parser->input.string.current == parser->input.string.end) {
+ *size_read = 0;
+ return 1;
+ }
+
+ if (size > (size_t)(parser->input.string.end
+ - parser->input.string.current)) {
+ size = parser->input.string.end - parser->input.string.current;
+ }
+
+ memcpy(buffer, parser->input.string.current, size);
+ parser->input.string.current += size;
+ *size_read = size;
+ return 1;
+}
+
+/*
+ * File read handler.
+ */
+
+static int
+yaml_file_read_handler(void *data, unsigned char *buffer, size_t size,
+ size_t *size_read)
+{
+ yaml_parser_t *parser = data;
+
+ *size_read = fread(buffer, 1, size, parser->input.file);
+ return !ferror(parser->input.file);
+}
+
+/*
+ * Set a string input.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_set_input_string(yaml_parser_t *parser,
+ const unsigned char *input, size_t size)
+{
+ assert(parser); /* Non-NULL parser object expected. */
+ assert(!parser->read_handler); /* You can set the source only once. */
+ assert(input); /* Non-NULL input string expected. */
+
+ parser->read_handler = yaml_string_read_handler;
+ parser->read_handler_data = parser;
+
+ parser->input.string.start = input;
+ parser->input.string.current = input;
+ parser->input.string.end = input+size;
+}
+
+/*
+ * Set a file input.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file)
+{
+ assert(parser); /* Non-NULL parser object expected. */
+ assert(!parser->read_handler); /* You can set the source only once. */
+ assert(file); /* Non-NULL file object expected. */
+
+ parser->read_handler = yaml_file_read_handler;
+ parser->read_handler_data = parser;
+
+ parser->input.file = file;
+}
+
+/*
+ * Set a generic input.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_set_input(yaml_parser_t *parser,
+ yaml_read_handler_t *handler, void *data)
+{
+ assert(parser); /* Non-NULL parser object expected. */
+ assert(!parser->read_handler); /* You can set the source only once. */
+ assert(handler); /* Non-NULL read handler expected. */
+
+ parser->read_handler = handler;
+ parser->read_handler_data = data;
+}
+
+/*
+ * Set the source encoding.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
+{
+ assert(parser); /* Non-NULL parser object expected. */
+ assert(!parser->encoding); /* Encoding is already set or detected. */
+
+ parser->encoding = encoding;
+}
+
+/*
+ * Create a new emitter object.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_initialize(yaml_emitter_t *emitter)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ memset(emitter, 0, sizeof(yaml_emitter_t));
+ if (!BUFFER_INIT(emitter, emitter->buffer, OUTPUT_BUFFER_SIZE))
+ goto error;
+ if (!BUFFER_INIT(emitter, emitter->raw_buffer, OUTPUT_RAW_BUFFER_SIZE))
+ goto error;
+ if (!STACK_INIT(emitter, emitter->states, INITIAL_STACK_SIZE))
+ goto error;
+ if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_SIZE))
+ goto error;
+ if (!STACK_INIT(emitter, emitter->indents, INITIAL_STACK_SIZE))
+ goto error;
+ if (!STACK_INIT(emitter, emitter->tag_directives, INITIAL_STACK_SIZE))
+ goto error;
+
+ return 1;
+
+error:
+
+ BUFFER_DEL(emitter, emitter->buffer);
+ BUFFER_DEL(emitter, emitter->raw_buffer);
+ STACK_DEL(emitter, emitter->states);
+ QUEUE_DEL(emitter, emitter->events);
+ STACK_DEL(emitter, emitter->indents);
+ STACK_DEL(emitter, emitter->tag_directives);
+
+ return 0;
+}
+
+/*
+ * Destroy an emitter object.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_delete(yaml_emitter_t *emitter)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ BUFFER_DEL(emitter, emitter->buffer);
+ BUFFER_DEL(emitter, emitter->raw_buffer);
+ STACK_DEL(emitter, emitter->states);
+ while (!QUEUE_EMPTY(emitter, emitter->events)) {
+ yaml_event_delete(&DEQUEUE(emitter, emitter->events));
+ }
+ QUEUE_DEL(emitter, emitter->events);
+ STACK_DEL(emitter, emitter->indents);
+ while (!STACK_EMPTY(empty, emitter->tag_directives)) {
+ yaml_tag_directive_t tag_directive = POP(emitter, emitter->tag_directives);
+ yaml_free(tag_directive.handle);
+ yaml_free(tag_directive.prefix);
+ }
+ STACK_DEL(emitter, emitter->tag_directives);
+ yaml_free(emitter->anchors);
+
+ memset(emitter, 0, sizeof(yaml_emitter_t));
+}
+
+/*
+ * String write handler.
+ */
+
+static int
+yaml_string_write_handler(void *data, unsigned char *buffer, size_t size)
+{
+ yaml_emitter_t *emitter = data;
+
+ if (emitter->output.string.size + *emitter->output.string.size_written
+ < size) {
+ memcpy(emitter->output.string.buffer
+ + *emitter->output.string.size_written,
+ buffer,
+ emitter->output.string.size
+ - *emitter->output.string.size_written);
+ *emitter->output.string.size_written = emitter->output.string.size;
+ return 0;
+ }
+
+ memcpy(emitter->output.string.buffer
+ + *emitter->output.string.size_written, buffer, size);
+ *emitter->output.string.size_written += size;
+ return 1;
+}
+
+/*
+ * File write handler.
+ */
+
+static int
+yaml_file_write_handler(void *data, unsigned char *buffer, size_t size)
+{
+ yaml_emitter_t *emitter = data;
+
+ return (fwrite(buffer, 1, size, emitter->output.file) == size);
+}
+/*
+ * Set a string output.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_output_string(yaml_emitter_t *emitter,
+ unsigned char *output, size_t size, size_t *size_written)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+ assert(!emitter->write_handler); /* You can set the output only once. */
+ assert(output); /* Non-NULL output string expected. */
+
+ emitter->write_handler = yaml_string_write_handler;
+ emitter->write_handler_data = emitter;
+
+ emitter->output.string.buffer = output;
+ emitter->output.string.size = size;
+ emitter->output.string.size_written = size_written;
+ *size_written = 0;
+}
+
+/*
+ * Set a file output.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+ assert(!emitter->write_handler); /* You can set the output only once. */
+ assert(file); /* Non-NULL file object expected. */
+
+ emitter->write_handler = yaml_file_write_handler;
+ emitter->write_handler_data = emitter;
+
+ emitter->output.file = file;
+}
+
+/*
+ * Set a generic output handler.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_output(yaml_emitter_t *emitter,
+ yaml_write_handler_t *handler, void *data)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+ assert(!emitter->write_handler); /* You can set the output only once. */
+ assert(handler); /* Non-NULL handler object expected. */
+
+ emitter->write_handler = handler;
+ emitter->write_handler_data = data;
+}
+
+/*
+ * Set the output encoding.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+ assert(!emitter->encoding); /* You can set encoding only once. */
+
+ emitter->encoding = encoding;
+}
+
+/*
+ * Set the canonical output style.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ emitter->canonical = (canonical != 0);
+}
+
+/*
+ * Set the indentation increment.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ emitter->best_indent = (1 < indent && indent < 10) ? indent : 2;
+}
+
+/*
+ * Set the preferred line width.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_width(yaml_emitter_t *emitter, int width)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ emitter->best_width = (width >= 0) ? width : -1;
+}
+
+/*
+ * Set if unescaped non-ASCII characters are allowed.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ emitter->unicode = (unicode != 0);
+}
+
+/*
+ * Set the preferred line break character.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break)
+{
+ assert(emitter); /* Non-NULL emitter object expected. */
+
+ emitter->line_break = line_break;
+}
+
+/*
+ * Destroy a token object.
+ */
+
+YAML_DECLARE(void)
+yaml_token_delete(yaml_token_t *token)
+{
+ assert(token); /* Non-NULL token object expected. */
+
+ switch (token->type)
+ {
+ case YAML_TAG_DIRECTIVE_TOKEN:
+ yaml_free(token->data.tag_directive.handle);
+ yaml_free(token->data.tag_directive.prefix);
+ break;
+
+ case YAML_ALIAS_TOKEN:
+ yaml_free(token->data.alias.value);
+ break;
+
+ case YAML_ANCHOR_TOKEN:
+ yaml_free(token->data.anchor.value);
+ break;
+
+ case YAML_TAG_TOKEN:
+ yaml_free(token->data.tag.handle);
+ yaml_free(token->data.tag.suffix);
+ break;
+
+ case YAML_SCALAR_TOKEN:
+ yaml_free(token->data.scalar.value);
+ break;
+
+ default:
+ break;
+ }
+
+ memset(token, 0, sizeof(yaml_token_t));
+}
+
+/*
+ * Check if a string is a valid UTF-8 sequence.
+ *
+ * Check 'reader.c' for more details on UTF-8 encoding.
+ */
+
+static int
+yaml_check_utf8(yaml_char_t *start, size_t length)
+{
+ yaml_char_t *end = start+length;
+ yaml_char_t *pointer = start;
+
+ while (pointer < end) {
+ unsigned char octet;
+ unsigned int width;
+ unsigned int value;
+ size_t k;
+
+ octet = pointer[0];
+ width = (octet & 0x80) == 0x00 ? 1 :
+ (octet & 0xE0) == 0xC0 ? 2 :
+ (octet & 0xF0) == 0xE0 ? 3 :
+ (octet & 0xF8) == 0xF0 ? 4 : 0;
+ value = (octet & 0x80) == 0x00 ? octet & 0x7F :
+ (octet & 0xE0) == 0xC0 ? octet & 0x1F :
+ (octet & 0xF0) == 0xE0 ? octet & 0x0F :
+ (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
+ if (!width) return 0;
+ if (pointer+width > end) return 0;
+ for (k = 1; k < width; k ++) {
+ octet = pointer[k];
+ if ((octet & 0xC0) != 0x80) return 0;
+ value = (value << 6) + (octet & 0x3F);
+ }
+ if (!((width == 1) ||
+ (width == 2 && value >= 0x80) ||
+ (width == 3 && value >= 0x800) ||
+ (width == 4 && value >= 0x10000))) return 0;
+
+ pointer += width;
+ }
+
+ return 1;
+}
+
+/*
+ * Create STREAM-START.
+ */
+
+YAML_DECLARE(int)
+yaml_stream_start_event_initialize(yaml_event_t *event,
+ yaml_encoding_t encoding)
+{
+ yaml_mark_t mark = { 0, 0, 0 };
+
+ assert(event); /* Non-NULL event object is expected. */
+
+ STREAM_START_EVENT_INIT(*event, encoding, mark, mark);
+
+ return 1;
+}
+
+/*
+ * Create STREAM-END.
+ */
+
+YAML_DECLARE(int)
+yaml_stream_end_event_initialize(yaml_event_t *event)
+{
+ yaml_mark_t mark = { 0, 0, 0 };
+
+ assert(event); /* Non-NULL event object is expected. */
+
+ STREAM_END_EVENT_INIT(*event, mark, mark);
+
+ return 1;
+}
+
+/*
+ * Create DOCUMENT-START.
+ */
+
+YAML_DECLARE(int)
+yaml_document_start_event_initialize(yaml_event_t *event,
+ yaml_titleVersion_directive_t *titleVersion_directive,
+ yaml_tag_directive_t *tag_directives_start,
+ yaml_tag_directive_t *tag_directives_end,
+ int implicit)
+{
+ struct {
+ yaml_error_type_t error;
+ } context;
+ yaml_mark_t mark = { 0, 0, 0 };
+ yaml_titleVersion_directive_t *titleVersion_directive_copy = NULL;
+ struct {
+ yaml_tag_directive_t *start;
+ yaml_tag_directive_t *end;
+ yaml_tag_directive_t *top;
+ } tag_directives_copy = { NULL, NULL, NULL };
+ yaml_tag_directive_t value = { NULL, NULL };
+
+ assert(event); /* Non-NULL event object is expected. */
+ assert((tag_directives_start && tag_directives_end) ||
+ (tag_directives_start == tag_directives_end));
+ /* Valid tag directives are expected. */
+
+ if (titleVersion_directive) {
+ titleVersion_directive_copy = yaml_malloc(sizeof(yaml_titleVersion_directive_t));
+ if (!titleVersion_directive_copy) goto error;
+ titleVersion_directive_copy->major = titleVersion_directive->major;
+ titleVersion_directive_copy->minor = titleVersion_directive->minor;
+ }
+
+ if (tag_directives_start != tag_directives_end) {
+ yaml_tag_directive_t *tag_directive;
+ if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
+ goto error;
+ for (tag_directive = tag_directives_start;
+ tag_directive != tag_directives_end; tag_directive ++) {
+ assert(tag_directive->handle);
+ assert(tag_directive->prefix);
+ if (!yaml_check_utf8(tag_directive->handle,
+ strlen((char *)tag_directive->handle)))
+ goto error;
+ if (!yaml_check_utf8(tag_directive->prefix,
+ strlen((char *)tag_directive->prefix)))
+ goto error;
+ value.handle = yaml_strdup(tag_directive->handle);
+ value.prefix = yaml_strdup(tag_directive->prefix);
+ if (!value.handle || !value.prefix) goto error;
+ if (!PUSH(&context, tag_directives_copy, value))
+ goto error;
+ value.handle = NULL;
+ value.prefix = NULL;
+ }
+ }
+
+ DOCUMENT_START_EVENT_INIT(*event, titleVersion_directive_copy,
+ tag_directives_copy.start, tag_directives_copy.top,
+ implicit, mark, mark);
+
+ return 1;
+
+error:
+ yaml_free(titleVersion_directive_copy);
+ while (!STACK_EMPTY(context, tag_directives_copy)) {
+ yaml_tag_directive_t value = POP(context, tag_directives_copy);
+ yaml_free(value.handle);
+ yaml_free(value.prefix);
+ }
+ STACK_DEL(context, tag_directives_copy);
+ yaml_free(value.handle);
+ yaml_free(value.prefix);
+
+ return 0;
+}
+
+/*
+ * Create DOCUMENT-END.
+ */
+
+YAML_DECLARE(int)
+yaml_document_end_event_initialize(yaml_event_t *event, int implicit)
+{
+ yaml_mark_t mark = { 0, 0, 0 };
+
+ assert(event); /* Non-NULL emitter object is expected. */
+
+ DOCUMENT_END_EVENT_INIT(*event, implicit, mark, mark);
+
+ return 1;
+}
+
+/*
+ * Create ALIAS.
+ */
+
+YAML_DECLARE(int)
+yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor)
+{
+ yaml_mark_t mark = { 0, 0, 0 };
+ yaml_char_t *anchor_copy = NULL;
+
+ assert(event); /* Non-NULL event object is expected. */
+ assert(anchor); /* Non-NULL anchor is expected. */
+
+ if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0;
+
+ anchor_copy = yaml_strdup(anchor);
+ if (!anchor_copy)
+ return 0;
+
+ ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark);
+
+ return 1;
+}
+
+/*
+ * Create SCALAR.
+ */
+
+YAML_DECLARE(int)
+yaml_scalar_event_initialize(yaml_event_t *event,
+ yaml_char_t *anchor, yaml_char_t *tag,
+ yaml_char_t *value, int length,
+ int plain_implicit, int quoted_implicit,
+ yaml_scalar_style_t style)
+{
+ yaml_mark_t mark = { 0, 0, 0 };
+ yaml_char_t *anchor_copy = NULL;
+ yaml_char_t *tag_copy = NULL;
+ yaml_char_t *value_copy = NULL;
+
+ assert(event); /* Non-NULL event object is expected. */
+ assert(value); /* Non-NULL anchor is expected. */
+
+ if (anchor) {
+ if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
+ anchor_copy = yaml_strdup(anchor);
+ if (!anchor_copy) goto error;
+ }
+
+ if (tag) {
+ if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
+ tag_copy = yaml_strdup(tag);
+ if (!tag_copy) goto error;
+ }
+
+ if (length < 0) {
+ length = strlen((char *)value);
+ }
+
+ if (!yaml_check_utf8(value, length)) goto error;
+ value_copy = yaml_malloc(length+1);
+ if (!value_copy) goto error;
+ memcpy(value_copy, value, length);
+ value_copy[length] = '\0';
+
+ SCALAR_EVENT_INIT(*event, anchor_copy, tag_copy, value_copy, length,
+ plain_implicit, quoted_implicit, style, mark, mark);
+
+ return 1;
+
+error:
+ yaml_free(anchor_copy);
+ yaml_free(tag_copy);
+ yaml_free(value_copy);
+
+ return 0;
+}
+
+/*
+ * Create SEQUENCE-START.
+ */
+
+YAML_DECLARE(int)
+yaml_sequence_start_event_initialize(yaml_event_t *event,
+ yaml_char_t *anchor, yaml_char_t *tag, int implicit,
+ yaml_sequence_style_t style)
+{
+ yaml_mark_t mark = { 0, 0, 0 };
+ yaml_char_t *anchor_copy = NULL;
+ yaml_char_t *tag_copy = NULL;
+
+ assert(event); /* Non-NULL event object is expected. */
+
+ if (anchor) {
+ if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
+ anchor_copy = yaml_strdup(anchor);
+ if (!anchor_copy) goto error;
+ }
+
+ if (tag) {
+ if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
+ tag_copy = yaml_strdup(tag);
+ if (!tag_copy) goto error;
+ }
+
+ SEQUENCE_START_EVENT_INIT(*event, anchor_copy, tag_copy,
+ implicit, style, mark, mark);
+
+ return 1;
+
+error:
+ yaml_free(anchor_copy);
+ yaml_free(tag_copy);
+
+ return 0;
+}
+
+/*
+ * Create SEQUENCE-END.
+ */
+
+YAML_DECLARE(int)
+yaml_sequence_end_event_initialize(yaml_event_t *event)
+{
+ yaml_mark_t mark = { 0, 0, 0 };
+
+ assert(event); /* Non-NULL event object is expected. */
+
+ SEQUENCE_END_EVENT_INIT(*event, mark, mark);
+
+ return 1;
+}
+
+/*
+ * Create MAPPING-START.
+ */
+
+YAML_DECLARE(int)
+yaml_mapping_start_event_initialize(yaml_event_t *event,
+ yaml_char_t *anchor, yaml_char_t *tag, int implicit,
+ yaml_mapping_style_t style)
+{
+ yaml_mark_t mark = { 0, 0, 0 };
+ yaml_char_t *anchor_copy = NULL;
+ yaml_char_t *tag_copy = NULL;
+
+ assert(event); /* Non-NULL event object is expected. */
+
+ if (anchor) {
+ if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
+ anchor_copy = yaml_strdup(anchor);
+ if (!anchor_copy) goto error;
+ }
+
+ if (tag) {
+ if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
+ tag_copy = yaml_strdup(tag);
+ if (!tag_copy) goto error;
+ }
+
+ MAPPING_START_EVENT_INIT(*event, anchor_copy, tag_copy,
+ implicit, style, mark, mark);
+
+ return 1;
+
+error:
+ yaml_free(anchor_copy);
+ yaml_free(tag_copy);
+
+ return 0;
+}
+
+/*
+ * Create MAPPING-END.
+ */
+
+YAML_DECLARE(int)
+yaml_mapping_end_event_initialize(yaml_event_t *event)
+{
+ yaml_mark_t mark = { 0, 0, 0 };
+
+ assert(event); /* Non-NULL event object is expected. */
+
+ MAPPING_END_EVENT_INIT(*event, mark, mark);
+
+ return 1;
+}
+
+/*
+ * Destroy an event object.
+ */
+
+YAML_DECLARE(void)
+yaml_event_delete(yaml_event_t *event)
+{
+ yaml_tag_directive_t *tag_directive;
+
+ assert(event); /* Non-NULL event object expected. */
+
+ switch (event->type)
+ {
+ case YAML_DOCUMENT_START_EVENT:
+ yaml_free(event->data.document_start.titleVersion_directive);
+ for (tag_directive = event->data.document_start.tag_directives.start;
+ tag_directive != event->data.document_start.tag_directives.end;
+ tag_directive++) {
+ yaml_free(tag_directive->handle);
+ yaml_free(tag_directive->prefix);
+ }
+ yaml_free(event->data.document_start.tag_directives.start);
+ break;
+
+ case YAML_ALIAS_EVENT:
+ yaml_free(event->data.alias.anchor);
+ break;
+
+ case YAML_SCALAR_EVENT:
+ yaml_free(event->data.scalar.anchor);
+ yaml_free(event->data.scalar.tag);
+ yaml_free(event->data.scalar.value);
+ break;
+
+ case YAML_SEQUENCE_START_EVENT:
+ yaml_free(event->data.sequence_start.anchor);
+ yaml_free(event->data.sequence_start.tag);
+ break;
+
+ case YAML_MAPPING_START_EVENT:
+ yaml_free(event->data.mapping_start.anchor);
+ yaml_free(event->data.mapping_start.tag);
+ break;
+
+ default:
+ break;
+ }
+
+ memset(event, 0, sizeof(yaml_event_t));
+}
+
+/*
+ * Create a document object.
+ */
+
+YAML_DECLARE(int)
+yaml_document_initialize(yaml_document_t *document,
+ yaml_titleVersion_directive_t *titleVersion_directive,
+ yaml_tag_directive_t *tag_directives_start,
+ yaml_tag_directive_t *tag_directives_end,
+ int start_implicit, int end_implicit)
+{
+ struct {
+ yaml_error_type_t error;
+ } context;
+ struct {
+ yaml_node_t *start;
+ yaml_node_t *end;
+ yaml_node_t *top;
+ } nodes = { NULL, NULL, NULL };
+ yaml_titleVersion_directive_t *titleVersion_directive_copy = NULL;
+ struct {
+ yaml_tag_directive_t *start;
+ yaml_tag_directive_t *end;
+ yaml_tag_directive_t *top;
+ } tag_directives_copy = { NULL, NULL, NULL };
+ yaml_tag_directive_t value = { NULL, NULL };
+ yaml_mark_t mark = { 0, 0, 0 };
+
+ assert(document); /* Non-NULL document object is expected. */
+ assert((tag_directives_start && tag_directives_end) ||
+ (tag_directives_start == tag_directives_end));
+ /* Valid tag directives are expected. */
+
+ if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error;
+
+ if (titleVersion_directive) {
+ titleVersion_directive_copy = yaml_malloc(sizeof(yaml_titleVersion_directive_t));
+ if (!titleVersion_directive_copy) goto error;
+ titleVersion_directive_copy->major = titleVersion_directive->major;
+ titleVersion_directive_copy->minor = titleVersion_directive->minor;
+ }
+
+ if (tag_directives_start != tag_directives_end) {
+ yaml_tag_directive_t *tag_directive;
+ if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
+ goto error;
+ for (tag_directive = tag_directives_start;
+ tag_directive != tag_directives_end; tag_directive ++) {
+ assert(tag_directive->handle);
+ assert(tag_directive->prefix);
+ if (!yaml_check_utf8(tag_directive->handle,
+ strlen((char *)tag_directive->handle)))
+ goto error;
+ if (!yaml_check_utf8(tag_directive->prefix,
+ strlen((char *)tag_directive->prefix)))
+ goto error;
+ value.handle = yaml_strdup(tag_directive->handle);
+ value.prefix = yaml_strdup(tag_directive->prefix);
+ if (!value.handle || !value.prefix) goto error;
+ if (!PUSH(&context, tag_directives_copy, value))
+ goto error;
+ value.handle = NULL;
+ value.prefix = NULL;
+ }
+ }
+
+ DOCUMENT_INIT(*document, nodes.start, nodes.end, titleVersion_directive_copy,
+ tag_directives_copy.start, tag_directives_copy.top,
+ start_implicit, end_implicit, mark, mark);
+
+ return 1;
+
+error:
+ STACK_DEL(&context, nodes);
+ yaml_free(titleVersion_directive_copy);
+ while (!STACK_EMPTY(&context, tag_directives_copy)) {
+ yaml_tag_directive_t value = POP(&context, tag_directives_copy);
+ yaml_free(value.handle);
+ yaml_free(value.prefix);
+ }
+ STACK_DEL(&context, tag_directives_copy);
+ yaml_free(value.handle);
+ yaml_free(value.prefix);
+
+ return 0;
+}
+
+/*
+ * Destroy a document object.
+ */
+
+YAML_DECLARE(void)
+yaml_document_delete(yaml_document_t *document)
+{
+ struct {
+ yaml_error_type_t error;
+ } context;
+ yaml_tag_directive_t *tag_directive;
+
+ context.error = YAML_NO_ERROR; /* Eliminate a compliler warning. */
+
+ assert(document); /* Non-NULL document object is expected. */
+
+ while (!STACK_EMPTY(&context, document->nodes)) {
+ yaml_node_t node = POP(&context, document->nodes);
+ yaml_free(node.tag);
+ switch (node.type) {
+ case YAML_SCALAR_NODE:
+ yaml_free(node.data.scalar.value);
+ break;
+ case YAML_SEQUENCE_NODE:
+ STACK_DEL(&context, node.data.sequence.items);
+ break;
+ case YAML_MAPPING_NODE:
+ STACK_DEL(&context, node.data.mapping.pairs);
+ break;
+ default:
+ assert(0); /* Should not happen. */
+ }
+ }
+ STACK_DEL(&context, document->nodes);
+
+ yaml_free(document->titleVersion_directive);
+ for (tag_directive = document->tag_directives.start;
+ tag_directive != document->tag_directives.end;
+ tag_directive++) {
+ yaml_free(tag_directive->handle);
+ yaml_free(tag_directive->prefix);
+ }
+ yaml_free(document->tag_directives.start);
+
+ memset(document, 0, sizeof(yaml_document_t));
+}
+
+/**
+ * Get a document node.
+ */
+
+YAML_DECLARE(yaml_node_t *)
+yaml_document_get_node(yaml_document_t *document, int index)
+{
+ assert(document); /* Non-NULL document object is expected. */
+
+ if (index > 0 && document->nodes.start + index <= document->nodes.top) {
+ return document->nodes.start + index - 1;
+ }
+ return NULL;
+}
+
+/**
+ * Get the root object.
+ */
+
+YAML_DECLARE(yaml_node_t *)
+yaml_document_get_root_node(yaml_document_t *document)
+{
+ assert(document); /* Non-NULL document object is expected. */
+
+ if (document->nodes.top != document->nodes.start) {
+ return document->nodes.start;
+ }
+ return NULL;
+}
+
+/*
+ * Add a scalar node to a document.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_scalar(yaml_document_t *document,
+ yaml_char_t *tag, yaml_char_t *value, int length,
+ yaml_scalar_style_t style)
+{
+ struct {
+ yaml_error_type_t error;
+ } context;
+ yaml_mark_t mark = { 0, 0, 0 };
+ yaml_char_t *tag_copy = NULL;
+ yaml_char_t *value_copy = NULL;
+ yaml_node_t node;
+
+ assert(document); /* Non-NULL document object is expected. */
+ assert(value); /* Non-NULL value is expected. */
+
+ if (!tag) {
+ tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG;
+ }
+
+ if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
+ tag_copy = yaml_strdup(tag);
+ if (!tag_copy) goto error;
+
+ if (length < 0) {
+ length = strlen((char *)value);
+ }
+
+ if (!yaml_check_utf8(value, length)) goto error;
+ value_copy = yaml_malloc(length+1);
+ if (!value_copy) goto error;
+ memcpy(value_copy, value, length);
+ value_copy[length] = '\0';
+
+ SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark);
+ if (!PUSH(&context, document->nodes, node)) goto error;
+
+ return document->nodes.top - document->nodes.start;
+
+error:
+ yaml_free(tag_copy);
+ yaml_free(value_copy);
+
+ return 0;
+}
+
+/*
+ * Add a sequence node to a document.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_sequence(yaml_document_t *document,
+ yaml_char_t *tag, yaml_sequence_style_t style)
+{
+ struct {
+ yaml_error_type_t error;
+ } context;
+ yaml_mark_t mark = { 0, 0, 0 };
+ yaml_char_t *tag_copy = NULL;
+ struct {
+ yaml_node_item_t *start;
+ yaml_node_item_t *end;
+ yaml_node_item_t *top;
+ } items = { NULL, NULL, NULL };
+ yaml_node_t node;
+
+ assert(document); /* Non-NULL document object is expected. */
+
+ if (!tag) {
+ tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG;
+ }
+
+ if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
+ tag_copy = yaml_strdup(tag);
+ if (!tag_copy) goto error;
+
+ if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error;
+
+ SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
+ style, mark, mark);
+ if (!PUSH(&context, document->nodes, node)) goto error;
+
+ return document->nodes.top - document->nodes.start;
+
+error:
+ STACK_DEL(&context, items);
+ yaml_free(tag_copy);
+
+ return 0;
+}
+
+/*
+ * Add a mapping node to a document.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_mapping(yaml_document_t *document,
+ yaml_char_t *tag, yaml_mapping_style_t style)
+{
+ struct {
+ yaml_error_type_t error;
+ } context;
+ yaml_mark_t mark = { 0, 0, 0 };
+ yaml_char_t *tag_copy = NULL;
+ struct {
+ yaml_node_pair_t *start;
+ yaml_node_pair_t *end;
+ yaml_node_pair_t *top;
+ } pairs = { NULL, NULL, NULL };
+ yaml_node_t node;
+
+ assert(document); /* Non-NULL document object is expected. */
+
+ if (!tag) {
+ tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG;
+ }
+
+ if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
+ tag_copy = yaml_strdup(tag);
+ if (!tag_copy) goto error;
+
+ if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error;
+
+ MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
+ style, mark, mark);
+ if (!PUSH(&context, document->nodes, node)) goto error;
+
+ return document->nodes.top - document->nodes.start;
+
+error:
+ STACK_DEL(&context, pairs);
+ yaml_free(tag_copy);
+
+ return 0;
+}
+
+/*
+ * Append an item to a sequence node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_append_sequence_item(yaml_document_t *document,
+ int sequence, int item)
+{
+ struct {
+ yaml_error_type_t error;
+ } context;
+
+ assert(document); /* Non-NULL document is required. */
+ assert(sequence > 0
+ && document->nodes.start + sequence <= document->nodes.top);
+ /* Valid sequence id is required. */
+ assert(document->nodes.start[sequence-1].type == YAML_SEQUENCE_NODE);
+ /* A sequence node is required. */
+ assert(item > 0 && document->nodes.start + item <= document->nodes.top);
+ /* Valid item id is required. */
+
+ if (!PUSH(&context,
+ document->nodes.start[sequence-1].data.sequence.items, item))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Append a pair of a key and a value to a mapping node.
+ */
+
+YAML_DECLARE(int)
+yaml_document_append_mapping_pair(yaml_document_t *document,
+ int mapping, int key, int value)
+{
+ struct {
+ yaml_error_type_t error;
+ } context;
+
+ yaml_node_pair_t pair;
+
+ assert(document); /* Non-NULL document is required. */
+ assert(mapping > 0
+ && document->nodes.start + mapping <= document->nodes.top);
+ /* Valid mapping id is required. */
+ assert(document->nodes.start[mapping-1].type == YAML_MAPPING_NODE);
+ /* A mapping node is required. */
+ assert(key > 0 && document->nodes.start + key <= document->nodes.top);
+ /* Valid key id is required. */
+ assert(value > 0 && document->nodes.start + value <= document->nodes.top);
+ /* Valid value id is required. */
+
+ pair.key = key;
+ pair.value = value;
+
+ if (!PUSH(&context,
+ document->nodes.start[mapping-1].data.mapping.pairs, pair))
+ return 0;
+
+ return 1;
+}
+
+
diff --git a/libyaml/dumper.c b/libyaml/dumper.c
new file mode 100644
index 0000000..4f89ab1
--- /dev/null
+++ b/libyaml/dumper.c
@@ -0,0 +1,394 @@
+
+#include "libyaml/yaml_private.h"
+
+/*
+ * API functions.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_open(yaml_emitter_t *emitter);
+
+YAML_DECLARE(int)
+yaml_emitter_close(yaml_emitter_t *emitter);
+
+YAML_DECLARE(int)
+yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document);
+
+/*
+ * Clean up functions.
+ */
+
+static void
+yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter);
+
+/*
+ * Anchor functions.
+ */
+
+static void
+yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index);
+
+static yaml_char_t *
+yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id);
+
+
+/*
+ * Serialize functions.
+ */
+
+static int
+yaml_emitter_dump_node(yaml_emitter_t *emitter, int index);
+
+static int
+yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor);
+
+static int
+yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
+ yaml_char_t *anchor);
+
+static int
+yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
+ yaml_char_t *anchor);
+
+static int
+yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
+ yaml_char_t *anchor);
+
+/*
+ * Issue a STREAM-START event.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_open(yaml_emitter_t *emitter)
+{
+ yaml_event_t event;
+ yaml_mark_t mark = { 0, 0, 0 };
+
+ assert(emitter); /* Non-NULL emitter object is required. */
+ assert(!emitter->opened); /* Emitter should not be opened yet. */
+
+ STREAM_START_EVENT_INIT(event, YAML_ANY_ENCODING, mark, mark);
+
+ if (!yaml_emitter_emit(emitter, &event)) {
+ return 0;
+ }
+
+ emitter->opened = 1;
+
+ return 1;
+}
+
+/*
+ * Issue a STREAM-END event.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_close(yaml_emitter_t *emitter)
+{
+ yaml_event_t event;
+ yaml_mark_t mark = { 0, 0, 0 };
+
+ assert(emitter); /* Non-NULL emitter object is required. */
+ assert(emitter->opened); /* Emitter should be opened. */
+
+ if (emitter->closed) return 1;
+
+ STREAM_END_EVENT_INIT(event, mark, mark);
+
+ if (!yaml_emitter_emit(emitter, &event)) {
+ return 0;
+ }
+
+ emitter->closed = 1;
+
+ return 1;
+}
+
+/*
+ * Dump a YAML document.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document)
+{
+ yaml_event_t event;
+ yaml_mark_t mark = { 0, 0, 0 };
+
+ assert(emitter); /* Non-NULL emitter object is required. */
+ assert(document); /* Non-NULL emitter object is expected. */
+
+ emitter->document = document;
+
+ if (!emitter->opened) {
+ if (!yaml_emitter_open(emitter)) goto error;
+ }
+
+ if (STACK_EMPTY(emitter, document->nodes)) {
+ if (!yaml_emitter_close(emitter)) goto error;
+ yaml_emitter_delete_document_and_anchors(emitter);
+ return 1;
+ }
+
+ assert(emitter->opened); /* Emitter should be opened. */
+
+ emitter->anchors = yaml_malloc(sizeof(*(emitter->anchors))
+ * (document->nodes.top - document->nodes.start));
+ if (!emitter->anchors) goto error;
+ memset(emitter->anchors, 0, sizeof(*(emitter->anchors))
+ * (document->nodes.top - document->nodes.start));
+
+ DOCUMENT_START_EVENT_INIT(event, document->titleVersion_directive,
+ document->tag_directives.start, document->tag_directives.end,
+ document->start_implicit, mark, mark);
+ if (!yaml_emitter_emit(emitter, &event)) goto error;
+
+ yaml_emitter_anchor_node(emitter, 1);
+ if (!yaml_emitter_dump_node(emitter, 1)) goto error;
+
+ DOCUMENT_END_EVENT_INIT(event, document->end_implicit, mark, mark);
+ if (!yaml_emitter_emit(emitter, &event)) goto error;
+
+ yaml_emitter_delete_document_and_anchors(emitter);
+
+ return 1;
+
+error:
+
+ yaml_emitter_delete_document_and_anchors(emitter);
+
+ return 0;
+}
+
+/*
+ * Clean up the emitter object after a document is dumped.
+ */
+
+static void
+yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter)
+{
+ int index;
+
+ if (!emitter->anchors) {
+ yaml_document_delete(emitter->document);
+ emitter->document = NULL;
+ return;
+ }
+
+ for (index = 0; emitter->document->nodes.start + index
+ < emitter->document->nodes.top; index ++) {
+ yaml_node_t node = emitter->document->nodes.start[index];
+ if (!emitter->anchors[index].serialized) {
+ yaml_free(node.tag);
+ if (node.type == YAML_SCALAR_NODE) {
+ yaml_free(node.data.scalar.value);
+ }
+ }
+ if (node.type == YAML_SEQUENCE_NODE) {
+ STACK_DEL(emitter, node.data.sequence.items);
+ }
+ if (node.type == YAML_MAPPING_NODE) {
+ STACK_DEL(emitter, node.data.mapping.pairs);
+ }
+ }
+
+ STACK_DEL(emitter, emitter->document->nodes);
+ yaml_free(emitter->anchors);
+
+ emitter->anchors = NULL;
+ emitter->last_anchor_id = 0;
+ emitter->document = NULL;
+}
+
+/*
+ * Check the references of a node and assign the anchor id if needed.
+ */
+
+static void
+yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index)
+{
+ yaml_node_t *node = emitter->document->nodes.start + index - 1;
+ yaml_node_item_t *item;
+ yaml_node_pair_t *pair;
+
+ emitter->anchors[index-1].references ++;
+
+ if (emitter->anchors[index-1].references == 1) {
+ switch (node->type) {
+ case YAML_SEQUENCE_NODE:
+ for (item = node->data.sequence.items.start;
+ item < node->data.sequence.items.top; item ++) {
+ yaml_emitter_anchor_node(emitter, *item);
+ }
+ break;
+ case YAML_MAPPING_NODE:
+ for (pair = node->data.mapping.pairs.start;
+ pair < node->data.mapping.pairs.top; pair ++) {
+ yaml_emitter_anchor_node(emitter, pair->key);
+ yaml_emitter_anchor_node(emitter, pair->value);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ else if (emitter->anchors[index-1].references == 2) {
+ emitter->anchors[index-1].anchor = (++ emitter->last_anchor_id);
+ }
+}
+
+/*
+ * Generate a textual representation for an anchor.
+ */
+
+#define ANCHOR_TEMPLATE "id%03d"
+#define ANCHOR_TEMPLATE_LENGTH 16
+
+static yaml_char_t *
+yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id)
+{
+ yaml_char_t *anchor = yaml_malloc(ANCHOR_TEMPLATE_LENGTH);
+
+ if (!anchor) return NULL;
+
+ sprintf((char *)anchor, ANCHOR_TEMPLATE, anchor_id);
+
+ return anchor;
+}
+
+/*
+ * Serialize a node.
+ */
+
+static int
+yaml_emitter_dump_node(yaml_emitter_t *emitter, int index)
+{
+ yaml_node_t *node = emitter->document->nodes.start + index - 1;
+ int anchor_id = emitter->anchors[index-1].anchor;
+ yaml_char_t *anchor = NULL;
+
+ if (anchor_id) {
+ anchor = yaml_emitter_generate_anchor(emitter, anchor_id);
+ if (!anchor) return 0;
+ }
+
+ if (emitter->anchors[index-1].serialized) {
+ return yaml_emitter_dump_alias(emitter, anchor);
+ }
+
+ emitter->anchors[index-1].serialized = 1;
+
+ switch (node->type) {
+ case YAML_SCALAR_NODE:
+ return yaml_emitter_dump_scalar(emitter, node, anchor);
+ case YAML_SEQUENCE_NODE:
+ return yaml_emitter_dump_sequence(emitter, node, anchor);
+ case YAML_MAPPING_NODE:
+ return yaml_emitter_dump_mapping(emitter, node, anchor);
+ default:
+ assert(0); /* Could not happen. */
+ break;
+ }
+
+ return 0; /* Could not happen. */
+}
+
+/*
+ * Serialize an alias.
+ */
+
+static int
+yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor)
+{
+ yaml_event_t event;
+ yaml_mark_t mark = { 0, 0, 0 };
+
+ ALIAS_EVENT_INIT(event, anchor, mark, mark);
+
+ return yaml_emitter_emit(emitter, &event);
+}
+
+/*
+ * Serialize a scalar.
+ */
+
+static int
+yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
+ yaml_char_t *anchor)
+{
+ yaml_event_t event;
+ yaml_mark_t mark = { 0, 0, 0 };
+
+ int plain_implicit = (strcmp((char *)node->tag,
+ YAML_DEFAULT_SCALAR_TAG) == 0);
+ int quoted_implicit = (strcmp((char *)node->tag,
+ YAML_DEFAULT_SCALAR_TAG) == 0);
+
+ SCALAR_EVENT_INIT(event, anchor, node->tag, node->data.scalar.value,
+ node->data.scalar.length, plain_implicit, quoted_implicit,
+ node->data.scalar.style, mark, mark);
+
+ return yaml_emitter_emit(emitter, &event);
+}
+
+/*
+ * Serialize a sequence.
+ */
+
+static int
+yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
+ yaml_char_t *anchor)
+{
+ yaml_event_t event;
+ yaml_mark_t mark = { 0, 0, 0 };
+
+ int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_SEQUENCE_TAG) == 0);
+
+ yaml_node_item_t *item;
+
+ SEQUENCE_START_EVENT_INIT(event, anchor, node->tag, implicit,
+ node->data.sequence.style, mark, mark);
+ if (!yaml_emitter_emit(emitter, &event)) return 0;
+
+ for (item = node->data.sequence.items.start;
+ item < node->data.sequence.items.top; item ++) {
+ if (!yaml_emitter_dump_node(emitter, *item)) return 0;
+ }
+
+ SEQUENCE_END_EVENT_INIT(event, mark, mark);
+ if (!yaml_emitter_emit(emitter, &event)) return 0;
+
+ return 1;
+}
+
+/*
+ * Serialize a mapping.
+ */
+
+static int
+yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
+ yaml_char_t *anchor)
+{
+ yaml_event_t event;
+ yaml_mark_t mark = { 0, 0, 0 };
+
+ int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_MAPPING_TAG) == 0);
+
+ yaml_node_pair_t *pair;
+
+ MAPPING_START_EVENT_INIT(event, anchor, node->tag, implicit,
+ node->data.mapping.style, mark, mark);
+ if (!yaml_emitter_emit(emitter, &event)) return 0;
+
+ for (pair = node->data.mapping.pairs.start;
+ pair < node->data.mapping.pairs.top; pair ++) {
+ if (!yaml_emitter_dump_node(emitter, pair->key)) return 0;
+ if (!yaml_emitter_dump_node(emitter, pair->value)) return 0;
+ }
+
+ MAPPING_END_EVENT_INIT(event, mark, mark);
+ if (!yaml_emitter_emit(emitter, &event)) return 0;
+
+ return 1;
+}
+
diff --git a/libyaml/emitter.c b/libyaml/emitter.c
new file mode 100644
index 0000000..5beab1f
--- /dev/null
+++ b/libyaml/emitter.c
@@ -0,0 +1,2329 @@
+
+#include "libyaml/yaml_private.h"
+
+/*
+ * Flush the buffer if needed.
+ */
+
+#define FLUSH(emitter) \
+ ((emitter->buffer.pointer+5 < emitter->buffer.end) \
+ || yaml_emitter_flush(emitter))
+
+/*
+ * Put a character to the output buffer.
+ */
+
+#define PUT(emitter,value) \
+ (FLUSH(emitter) \
+ && (*(emitter->buffer.pointer++) = (yaml_char_t)(value), \
+ emitter->column ++, \
+ 1))
+
+/*
+ * Put a line break to the output buffer.
+ */
+
+#define PUT_BREAK(emitter) \
+ (FLUSH(emitter) \
+ && ((emitter->line_break == YAML_CR_BREAK ? \
+ (*(emitter->buffer.pointer++) = (yaml_char_t) '\r') : \
+ emitter->line_break == YAML_LN_BREAK ? \
+ (*(emitter->buffer.pointer++) = (yaml_char_t) '\n') : \
+ emitter->line_break == YAML_CRLN_BREAK ? \
+ (*(emitter->buffer.pointer++) = (yaml_char_t) '\r', \
+ *(emitter->buffer.pointer++) = (yaml_char_t) '\n') : 0), \
+ emitter->column = 0, \
+ emitter->line ++, \
+ 1))
+
+/*
+ * Copy a character from a string into buffer.
+ */
+
+#define WRITE(emitter,string) \
+ (FLUSH(emitter) \
+ && (COPY(emitter->buffer,string), \
+ emitter->column ++, \
+ 1))
+
+/*
+ * Copy a line break character from a string into buffer.
+ */
+
+#define WRITE_BREAK(emitter,string) \
+ (FLUSH(emitter) \
+ && (CHECK(string,'\n') ? \
+ (PUT_BREAK(emitter), \
+ string.pointer ++, \
+ 1) : \
+ (COPY(emitter->buffer,string), \
+ emitter->column = 0, \
+ emitter->line ++, \
+ 1)))
+
+/*
+ * API functions.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event);
+
+/*
+ * Utility functions.
+ */
+
+static int
+yaml_emitter_set_emitter_error(yaml_emitter_t *emitter, const char *problem);
+
+static int
+yaml_emitter_need_more_events(yaml_emitter_t *emitter);
+
+static int
+yaml_emitter_append_tag_directive(yaml_emitter_t *emitter,
+ yaml_tag_directive_t value, int allow_duplicates);
+
+static int
+yaml_emitter_increase_indent(yaml_emitter_t *emitter,
+ int flow, int indentless);
+
+/*
+ * State functions.
+ */
+
+static int
+yaml_emitter_state_machine(yaml_emitter_t *emitter, yaml_event_t *event);
+
+static int
+yaml_emitter_emit_stream_start(yaml_emitter_t *emitter,
+ yaml_event_t *event);
+
+static int
+yaml_emitter_emit_document_start(yaml_emitter_t *emitter,
+ yaml_event_t *event, int first);
+
+static int
+yaml_emitter_emit_document_content(yaml_emitter_t *emitter,
+ yaml_event_t *event);
+
+static int
+yaml_emitter_emit_document_end(yaml_emitter_t *emitter,
+ yaml_event_t *event);
+
+static int
+yaml_emitter_emit_flow_sequence_item(yaml_emitter_t *emitter,
+ yaml_event_t *event, int first);
+
+static int
+yaml_emitter_emit_flow_mapping_key(yaml_emitter_t *emitter,
+ yaml_event_t *event, int first);
+
+static int
+yaml_emitter_emit_flow_mapping_value(yaml_emitter_t *emitter,
+ yaml_event_t *event, int simple);
+
+static int
+yaml_emitter_emit_block_sequence_item(yaml_emitter_t *emitter,
+ yaml_event_t *event, int first);
+
+static int
+yaml_emitter_emit_block_mapping_key(yaml_emitter_t *emitter,
+ yaml_event_t *event, int first);
+
+static int
+yaml_emitter_emit_block_mapping_value(yaml_emitter_t *emitter,
+ yaml_event_t *event, int simple);
+
+static int
+yaml_emitter_emit_node(yaml_emitter_t *emitter, yaml_event_t *event,
+ int root, int sequence, int mapping, int simple_key);
+
+static int
+yaml_emitter_emit_alias(yaml_emitter_t *emitter, yaml_event_t *event);
+
+static int
+yaml_emitter_emit_scalar(yaml_emitter_t *emitter, yaml_event_t *event);
+
+static int
+yaml_emitter_emit_sequence_start(yaml_emitter_t *emitter, yaml_event_t *event);
+
+static int
+yaml_emitter_emit_mapping_start(yaml_emitter_t *emitter, yaml_event_t *event);
+
+/*
+ * Checkers.
+ */
+
+static int
+yaml_emitter_check_empty_document(yaml_emitter_t *emitter);
+
+static int
+yaml_emitter_check_empty_sequence(yaml_emitter_t *emitter);
+
+static int
+yaml_emitter_check_empty_mapping(yaml_emitter_t *emitter);
+
+static int
+yaml_emitter_check_simple_key(yaml_emitter_t *emitter);
+
+static int
+yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event);
+
+/*
+ * Processors.
+ */
+
+static int
+yaml_emitter_process_anchor(yaml_emitter_t *emitter);
+
+static int
+yaml_emitter_process_tag(yaml_emitter_t *emitter);
+
+static int
+yaml_emitter_process_scalar(yaml_emitter_t *emitter);
+
+/*
+ * Analyzers.
+ */
+
+static int
+yaml_emitter_analyze_titleVersion_directive(yaml_emitter_t *emitter,
+ yaml_titleVersion_directive_t titleVersion_directive);
+
+static int
+yaml_emitter_analyze_tag_directive(yaml_emitter_t *emitter,
+ yaml_tag_directive_t tag_directive);
+
+static int
+yaml_emitter_analyze_anchor(yaml_emitter_t *emitter,
+ yaml_char_t *anchor, int alias);
+
+static int
+yaml_emitter_analyze_tag(yaml_emitter_t *emitter,
+ yaml_char_t *tag);
+
+static int
+yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length);
+
+static int
+yaml_emitter_analyze_event(yaml_emitter_t *emitter,
+ yaml_event_t *event);
+
+/*
+ * Writers.
+ */
+
+static int
+yaml_emitter_write_bom(yaml_emitter_t *emitter);
+
+static int
+yaml_emitter_write_indent(yaml_emitter_t *emitter);
+
+static int
+yaml_emitter_write_indicator(yaml_emitter_t *emitter,
+ char *indicator, int need_whitespace,
+ int is_whitespace, int is_indention);
+
+static int
+yaml_emitter_write_anchor(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length);
+
+static int
+yaml_emitter_write_tag_handle(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length);
+
+static int
+yaml_emitter_write_tag_content(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length, int need_whitespace);
+
+static int
+yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length, int allow_breaks);
+
+static int
+yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length, int allow_breaks);
+
+static int
+yaml_emitter_write_double_quoted_scalar(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length, int allow_breaks);
+
+static int
+yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter,
+ yaml_string_t string);
+
+static int
+yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length);
+
+static int
+yaml_emitter_write_folded_scalar(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length);
+
+/*
+ * Set an emitter error and return 0.
+ */
+
+static int
+yaml_emitter_set_emitter_error(yaml_emitter_t *emitter, const char *problem)
+{
+ emitter->error = YAML_EMITTER_ERROR;
+ emitter->problem = problem;
+
+ return 0;
+}
+
+/*
+ * Emit an event.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event)
+{
+ if (!ENQUEUE(emitter, emitter->events, *event)) {
+ yaml_event_delete(event);
+ return 0;
+ }
+
+ while (!yaml_emitter_need_more_events(emitter)) {
+ if (!yaml_emitter_analyze_event(emitter, emitter->events.head))
+ return 0;
+ if (!yaml_emitter_state_machine(emitter, emitter->events.head))
+ return 0;
+ yaml_event_delete(&DEQUEUE(emitter, emitter->events));
+ }
+
+ return 1;
+}
+
+/*
+ * Check if we need to accumulate more events before emitting.
+ *
+ * We accumulate extra
+ * - 1 event for DOCUMENT-START
+ * - 2 events for SEQUENCE-START
+ * - 3 events for MAPPING-START
+ */
+
+static int
+yaml_emitter_need_more_events(yaml_emitter_t *emitter)
+{
+ int level = 0;
+ int accumulate = 0;
+ yaml_event_t *event;
+
+ if (QUEUE_EMPTY(emitter, emitter->events))
+ return 1;
+
+ switch (emitter->events.head->type) {
+ case YAML_DOCUMENT_START_EVENT:
+ accumulate = 1;
+ break;
+ case YAML_SEQUENCE_START_EVENT:
+ accumulate = 2;
+ break;
+ case YAML_MAPPING_START_EVENT:
+ accumulate = 3;
+ break;
+ default:
+ return 0;
+ }
+
+ if (emitter->events.tail - emitter->events.head > accumulate)
+ return 0;
+
+ for (event = emitter->events.head; event != emitter->events.tail; event ++) {
+ switch (event->type) {
+ case YAML_STREAM_START_EVENT:
+ case YAML_DOCUMENT_START_EVENT:
+ case YAML_SEQUENCE_START_EVENT:
+ case YAML_MAPPING_START_EVENT:
+ level += 1;
+ break;
+ case YAML_STREAM_END_EVENT:
+ case YAML_DOCUMENT_END_EVENT:
+ case YAML_SEQUENCE_END_EVENT:
+ case YAML_MAPPING_END_EVENT:
+ level -= 1;
+ break;
+ default:
+ break;
+ }
+ if (!level)
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Append a directive to the directives stack.
+ */
+
+static int
+yaml_emitter_append_tag_directive(yaml_emitter_t *emitter,
+ yaml_tag_directive_t value, int allow_duplicates)
+{
+ yaml_tag_directive_t *tag_directive;
+ yaml_tag_directive_t copy = { NULL, NULL };
+
+ for (tag_directive = emitter->tag_directives.start;
+ tag_directive != emitter->tag_directives.top; tag_directive ++) {
+ if (strcmp((char *)value.handle, (char *)tag_directive->handle) == 0) {
+ if (allow_duplicates)
+ return 1;
+ return yaml_emitter_set_emitter_error(emitter,
+ "duplicate %TAG directive");
+ }
+ }
+
+ copy.handle = yaml_strdup(value.handle);
+ copy.prefix = yaml_strdup(value.prefix);
+ if (!copy.handle || !copy.prefix) {
+ emitter->error = YAML_MEMORY_ERROR;
+ goto error;
+ }
+
+ if (!PUSH(emitter, emitter->tag_directives, copy))
+ goto error;
+
+ return 1;
+
+error:
+ yaml_free(copy.handle);
+ yaml_free(copy.prefix);
+ return 0;
+}
+
+/*
+ * Increase the indentation level.
+ */
+
+static int
+yaml_emitter_increase_indent(yaml_emitter_t *emitter,
+ int flow, int indentless)
+{
+ if (!PUSH(emitter, emitter->indents, emitter->indent))
+ return 0;
+
+ if (emitter->indent < 0) {
+ emitter->indent = flow ? emitter->best_indent : 0;
+ }
+ else if (!indentless) {
+ emitter->indent += emitter->best_indent;
+ }
+
+ return 1;
+}
+
+/*
+ * State dispatcher.
+ */
+
+static int
+yaml_emitter_state_machine(yaml_emitter_t *emitter, yaml_event_t *event)
+{
+ switch (emitter->state)
+ {
+ case YAML_EMIT_STREAM_START_STATE:
+ return yaml_emitter_emit_stream_start(emitter, event);
+
+ case YAML_EMIT_FIRST_DOCUMENT_START_STATE:
+ return yaml_emitter_emit_document_start(emitter, event, 1);
+
+ case YAML_EMIT_DOCUMENT_START_STATE:
+ return yaml_emitter_emit_document_start(emitter, event, 0);
+
+ case YAML_EMIT_DOCUMENT_CONTENT_STATE:
+ return yaml_emitter_emit_document_content(emitter, event);
+
+ case YAML_EMIT_DOCUMENT_END_STATE:
+ return yaml_emitter_emit_document_end(emitter, event);
+
+ case YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, 1);
+
+ case YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, 0);
+
+ case YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, 1);
+
+ case YAML_EMIT_FLOW_MAPPING_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, 0);
+
+ case YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
+ return yaml_emitter_emit_flow_mapping_value(emitter, event, 1);
+
+ case YAML_EMIT_FLOW_MAPPING_VALUE_STATE:
+ return yaml_emitter_emit_flow_mapping_value(emitter, event, 0);
+
+ case YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
+ return yaml_emitter_emit_block_sequence_item(emitter, event, 1);
+
+ case YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
+ return yaml_emitter_emit_block_sequence_item(emitter, event, 0);
+
+ case YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return yaml_emitter_emit_block_mapping_key(emitter, event, 1);
+
+ case YAML_EMIT_BLOCK_MAPPING_KEY_STATE:
+ return yaml_emitter_emit_block_mapping_key(emitter, event, 0);
+
+ case YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
+ return yaml_emitter_emit_block_mapping_value(emitter, event, 1);
+
+ case YAML_EMIT_BLOCK_MAPPING_VALUE_STATE:
+ return yaml_emitter_emit_block_mapping_value(emitter, event, 0);
+
+ case YAML_EMIT_END_STATE:
+ return yaml_emitter_set_emitter_error(emitter,
+ "expected nothing after STREAM-END");
+
+ default:
+ assert(1); /* Invalid state. */
+ }
+
+ return 0;
+}
+
+/*
+ * Expect STREAM-START.
+ */
+
+static int
+yaml_emitter_emit_stream_start(yaml_emitter_t *emitter,
+ yaml_event_t *event)
+{
+ if (event->type == YAML_STREAM_START_EVENT)
+ {
+ if (!emitter->encoding) {
+ emitter->encoding = event->data.stream_start.encoding;
+ }
+
+ if (!emitter->encoding) {
+ emitter->encoding = YAML_UTF8_ENCODING;
+ }
+
+ if (emitter->best_indent < 2 || emitter->best_indent > 9) {
+ emitter->best_indent = 2;
+ }
+
+ if (emitter->best_width >= 0
+ && emitter->best_width <= emitter->best_indent*2) {
+ emitter->best_width = 80;
+ }
+
+ if (emitter->best_width < 0) {
+ emitter->best_width = INT_MAX;
+ }
+
+ if (!emitter->line_break) {
+ emitter->line_break = YAML_LN_BREAK;
+ }
+
+ emitter->indent = -1;
+
+ emitter->line = 0;
+ emitter->column = 0;
+ emitter->whitespace = 1;
+ emitter->indention = 1;
+
+ if (emitter->encoding != YAML_UTF8_ENCODING) {
+ if (!yaml_emitter_write_bom(emitter))
+ return 0;
+ }
+
+ emitter->state = YAML_EMIT_FIRST_DOCUMENT_START_STATE;
+
+ return 1;
+ }
+
+ return yaml_emitter_set_emitter_error(emitter,
+ "expected STREAM-START");
+}
+
+/*
+ * Expect DOCUMENT-START or STREAM-END.
+ */
+
+static int
+yaml_emitter_emit_document_start(yaml_emitter_t *emitter,
+ yaml_event_t *event, int first)
+{
+ if (event->type == YAML_DOCUMENT_START_EVENT)
+ {
+ yaml_tag_directive_t default_tag_directives[] = {
+ {(yaml_char_t *)"!", (yaml_char_t *)"!"},
+ {(yaml_char_t *)"!!", (yaml_char_t *)"tag:yaml.org,2002:"},
+ {NULL, NULL}
+ };
+ yaml_tag_directive_t *tag_directive;
+ int implicit;
+
+ if (event->data.document_start.titleVersion_directive) {
+ if (!yaml_emitter_analyze_titleVersion_directive(emitter,
+ *event->data.document_start.titleVersion_directive))
+ return 0;
+ }
+
+ for (tag_directive = event->data.document_start.tag_directives.start;
+ tag_directive != event->data.document_start.tag_directives.end;
+ tag_directive ++) {
+ if (!yaml_emitter_analyze_tag_directive(emitter, *tag_directive))
+ return 0;
+ if (!yaml_emitter_append_tag_directive(emitter, *tag_directive, 0))
+ return 0;
+ }
+
+ for (tag_directive = default_tag_directives;
+ tag_directive->handle; tag_directive ++) {
+ if (!yaml_emitter_append_tag_directive(emitter, *tag_directive, 1))
+ return 0;
+ }
+
+ implicit = event->data.document_start.implicit;
+ if (!first || emitter->canonical) {
+ implicit = 0;
+ }
+
+ if ((event->data.document_start.titleVersion_directive ||
+ (event->data.document_start.tag_directives.start
+ != event->data.document_start.tag_directives.end)) &&
+ emitter->open_ended)
+ {
+ if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0))
+ return 0;
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ }
+
+ if (event->data.document_start.titleVersion_directive) {
+ implicit = 0;
+ if (!yaml_emitter_write_indicator(emitter, "%YAML", 1, 0, 0))
+ return 0;
+ if (!yaml_emitter_write_indicator(emitter, "1.1", 1, 0, 0))
+ return 0;
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ }
+
+ if (event->data.document_start.tag_directives.start
+ != event->data.document_start.tag_directives.end) {
+ implicit = 0;
+ for (tag_directive = event->data.document_start.tag_directives.start;
+ tag_directive != event->data.document_start.tag_directives.end;
+ tag_directive ++) {
+ if (!yaml_emitter_write_indicator(emitter, "%TAG", 1, 0, 0))
+ return 0;
+ if (!yaml_emitter_write_tag_handle(emitter, tag_directive->handle,
+ strlen((char *)tag_directive->handle)))
+ return 0;
+ if (!yaml_emitter_write_tag_content(emitter, tag_directive->prefix,
+ strlen((char *)tag_directive->prefix), 1))
+ return 0;
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ }
+ }
+
+ if (yaml_emitter_check_empty_document(emitter)) {
+ implicit = 0;
+ }
+
+ if (!implicit) {
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ if (!yaml_emitter_write_indicator(emitter, "---", 1, 0, 0))
+ return 0;
+ if (emitter->canonical) {
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ }
+ }
+
+ emitter->state = YAML_EMIT_DOCUMENT_CONTENT_STATE;
+
+ return 1;
+ }
+
+ else if (event->type == YAML_STREAM_END_EVENT)
+ {
+ if (emitter->open_ended)
+ {
+ if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0))
+ return 0;
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ }
+
+ if (!yaml_emitter_flush(emitter))
+ return 0;
+
+ emitter->state = YAML_EMIT_END_STATE;
+
+ return 1;
+ }
+
+ return yaml_emitter_set_emitter_error(emitter,
+ "expected DOCUMENT-START or STREAM-END");
+}
+
+/*
+ * Expect the root node.
+ */
+
+static int
+yaml_emitter_emit_document_content(yaml_emitter_t *emitter,
+ yaml_event_t *event)
+{
+ if (!PUSH(emitter, emitter->states, YAML_EMIT_DOCUMENT_END_STATE))
+ return 0;
+
+ return yaml_emitter_emit_node(emitter, event, 1, 0, 0, 0);
+}
+
+/*
+ * Expect DOCUMENT-END.
+ */
+
+static int
+yaml_emitter_emit_document_end(yaml_emitter_t *emitter,
+ yaml_event_t *event)
+{
+ if (event->type == YAML_DOCUMENT_END_EVENT)
+ {
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ if (!event->data.document_end.implicit) {
+ if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0))
+ return 0;
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ }
+ if (!yaml_emitter_flush(emitter))
+ return 0;
+
+ emitter->state = YAML_EMIT_DOCUMENT_START_STATE;
+
+ while (!STACK_EMPTY(emitter, emitter->tag_directives)) {
+ yaml_tag_directive_t tag_directive = POP(emitter,
+ emitter->tag_directives);
+ yaml_free(tag_directive.handle);
+ yaml_free(tag_directive.prefix);
+ }
+
+ return 1;
+ }
+
+ return yaml_emitter_set_emitter_error(emitter,
+ "expected DOCUMENT-END");
+}
+
+/*
+ *
+ * Expect a flow item node.
+ */
+
+static int
+yaml_emitter_emit_flow_sequence_item(yaml_emitter_t *emitter,
+ yaml_event_t *event, int first)
+{
+ if (first)
+ {
+ if (!yaml_emitter_write_indicator(emitter, "[", 1, 1, 0))
+ return 0;
+ if (!yaml_emitter_increase_indent(emitter, 1, 0))
+ return 0;
+ emitter->flow_level ++;
+ }
+
+ if (event->type == YAML_SEQUENCE_END_EVENT)
+ {
+ emitter->flow_level --;
+ emitter->indent = POP(emitter, emitter->indents);
+ if (emitter->canonical && !first) {
+ if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
+ return 0;
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ }
+ if (!yaml_emitter_write_indicator(emitter, "]", 0, 0, 0))
+ return 0;
+ emitter->state = POP(emitter, emitter->states);
+
+ return 1;
+ }
+
+ if (!first) {
+ if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
+ return 0;
+ }
+
+ if (emitter->canonical || emitter->column > emitter->best_width) {
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ }
+ if (!PUSH(emitter, emitter->states, YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE))
+ return 0;
+
+ return yaml_emitter_emit_node(emitter, event, 0, 1, 0, 0);
+}
+
+/*
+ * Expect a flow key node.
+ */
+
+static int
+yaml_emitter_emit_flow_mapping_key(yaml_emitter_t *emitter,
+ yaml_event_t *event, int first)
+{
+ if (first)
+ {
+ if (!yaml_emitter_write_indicator(emitter, "{", 1, 1, 0))
+ return 0;
+ if (!yaml_emitter_increase_indent(emitter, 1, 0))
+ return 0;
+ emitter->flow_level ++;
+ }
+
+ if (event->type == YAML_MAPPING_END_EVENT)
+ {
+ emitter->flow_level --;
+ emitter->indent = POP(emitter, emitter->indents);
+ if (emitter->canonical && !first) {
+ if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
+ return 0;
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ }
+ if (!yaml_emitter_write_indicator(emitter, "}", 0, 0, 0))
+ return 0;
+ emitter->state = POP(emitter, emitter->states);
+
+ return 1;
+ }
+
+ if (!first) {
+ if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
+ return 0;
+ }
+ if (emitter->canonical || emitter->column > emitter->best_width) {
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ }
+
+ if (!emitter->canonical && yaml_emitter_check_simple_key(emitter))
+ {
+ if (!PUSH(emitter, emitter->states,
+ YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE))
+ return 0;
+
+ return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 1);
+ }
+ else
+ {
+ if (!yaml_emitter_write_indicator(emitter, "?", 1, 0, 0))
+ return 0;
+ if (!PUSH(emitter, emitter->states,
+ YAML_EMIT_FLOW_MAPPING_VALUE_STATE))
+ return 0;
+
+ return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
+ }
+}
+
+/*
+ * Expect a flow value node.
+ */
+
+static int
+yaml_emitter_emit_flow_mapping_value(yaml_emitter_t *emitter,
+ yaml_event_t *event, int simple)
+{
+ if (simple) {
+ if (!yaml_emitter_write_indicator(emitter, ":", 0, 0, 0))
+ return 0;
+ }
+ else {
+ if (emitter->canonical || emitter->column > emitter->best_width) {
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ }
+ if (!yaml_emitter_write_indicator(emitter, ":", 1, 0, 0))
+ return 0;
+ }
+ if (!PUSH(emitter, emitter->states, YAML_EMIT_FLOW_MAPPING_KEY_STATE))
+ return 0;
+ return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
+}
+
+/*
+ * Expect a block item node.
+ */
+
+static int
+yaml_emitter_emit_block_sequence_item(yaml_emitter_t *emitter,
+ yaml_event_t *event, int first)
+{
+ if (first)
+ {
+ if (!yaml_emitter_increase_indent(emitter, 0,
+ (emitter->mapping_context && !emitter->indention)))
+ return 0;
+ }
+
+ if (event->type == YAML_SEQUENCE_END_EVENT)
+ {
+ emitter->indent = POP(emitter, emitter->indents);
+ emitter->state = POP(emitter, emitter->states);
+
+ return 1;
+ }
+
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ if (!yaml_emitter_write_indicator(emitter, "-", 1, 0, 1))
+ return 0;
+ if (!PUSH(emitter, emitter->states,
+ YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE))
+ return 0;
+
+ return yaml_emitter_emit_node(emitter, event, 0, 1, 0, 0);
+}
+
+/*
+ * Expect a block key node.
+ */
+
+static int
+yaml_emitter_emit_block_mapping_key(yaml_emitter_t *emitter,
+ yaml_event_t *event, int first)
+{
+ if (first)
+ {
+ if (!yaml_emitter_increase_indent(emitter, 0, 0))
+ return 0;
+ }
+
+ if (event->type == YAML_MAPPING_END_EVENT)
+ {
+ emitter->indent = POP(emitter, emitter->indents);
+ emitter->state = POP(emitter, emitter->states);
+
+ return 1;
+ }
+
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+
+ if (yaml_emitter_check_simple_key(emitter))
+ {
+ if (!PUSH(emitter, emitter->states,
+ YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE))
+ return 0;
+
+ return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 1);
+ }
+ else
+ {
+ if (!yaml_emitter_write_indicator(emitter, "?", 1, 0, 1))
+ return 0;
+ if (!PUSH(emitter, emitter->states,
+ YAML_EMIT_BLOCK_MAPPING_VALUE_STATE))
+ return 0;
+
+ return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
+ }
+}
+
+/*
+ * Expect a block value node.
+ */
+
+static int
+yaml_emitter_emit_block_mapping_value(yaml_emitter_t *emitter,
+ yaml_event_t *event, int simple)
+{
+ if (simple) {
+ if (!yaml_emitter_write_indicator(emitter, ":", 0, 0, 0))
+ return 0;
+ }
+ else {
+ if (!yaml_emitter_write_indent(emitter))
+ return 0;
+ if (!yaml_emitter_write_indicator(emitter, ":", 1, 0, 1))
+ return 0;
+ }
+ if (!PUSH(emitter, emitter->states,
+ YAML_EMIT_BLOCK_MAPPING_KEY_STATE))
+ return 0;
+
+ return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
+}
+
+/*
+ * Expect a node.
+ */
+
+static int
+yaml_emitter_emit_node(yaml_emitter_t *emitter, yaml_event_t *event,
+ int root, int sequence, int mapping, int simple_key)
+{
+ emitter->root_context = root;
+ emitter->sequence_context = sequence;
+ emitter->mapping_context = mapping;
+ emitter->simple_key_context = simple_key;
+
+ switch (event->type)
+ {
+ case YAML_ALIAS_EVENT:
+ return yaml_emitter_emit_alias(emitter, event);
+
+ case YAML_SCALAR_EVENT:
+ return yaml_emitter_emit_scalar(emitter, event);
+
+ case YAML_SEQUENCE_START_EVENT:
+ return yaml_emitter_emit_sequence_start(emitter, event);
+
+ case YAML_MAPPING_START_EVENT:
+ return yaml_emitter_emit_mapping_start(emitter, event);
+
+ default:
+ return yaml_emitter_set_emitter_error(emitter,
+ "expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS");
+ }
+
+ return 0;
+}
+
+/*
+ * Expect ALIAS.
+ */
+
+static int
+yaml_emitter_emit_alias(yaml_emitter_t *emitter, yaml_event_t *event)
+{
+ if (!yaml_emitter_process_anchor(emitter))
+ return 0;
+ emitter->state = POP(emitter, emitter->states);
+
+ return 1;
+}
+
+/*
+ * Expect SCALAR.
+ */
+
+static int
+yaml_emitter_emit_scalar(yaml_emitter_t *emitter, yaml_event_t *event)
+{
+ if (!yaml_emitter_select_scalar_style(emitter, event))
+ return 0;
+ if (!yaml_emitter_process_anchor(emitter))
+ return 0;
+ if (!yaml_emitter_process_tag(emitter))
+ return 0;
+ if (!yaml_emitter_increase_indent(emitter, 1, 0))
+ return 0;
+ if (!yaml_emitter_process_scalar(emitter))
+ return 0;
+ emitter->indent = POP(emitter, emitter->indents);
+ emitter->state = POP(emitter, emitter->states);
+
+ return 1;
+}
+
+/*
+ * Expect SEQUENCE-START.
+ */
+
+static int
+yaml_emitter_emit_sequence_start(yaml_emitter_t *emitter, yaml_event_t *event)
+{
+ if (!yaml_emitter_process_anchor(emitter))
+ return 0;
+ if (!yaml_emitter_process_tag(emitter))
+ return 0;
+
+ if (emitter->flow_level || emitter->canonical
+ || event->data.sequence_start.style == YAML_FLOW_SEQUENCE_STYLE
+ || yaml_emitter_check_empty_sequence(emitter)) {
+ emitter->state = YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE;
+ }
+ else {
+ emitter->state = YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE;
+ }
+
+ return 1;
+}
+
+/*
+ * Expect MAPPING-START.
+ */
+
+static int
+yaml_emitter_emit_mapping_start(yaml_emitter_t *emitter, yaml_event_t *event)
+{
+ if (!yaml_emitter_process_anchor(emitter))
+ return 0;
+ if (!yaml_emitter_process_tag(emitter))
+ return 0;
+
+ if (emitter->flow_level || emitter->canonical
+ || event->data.mapping_start.style == YAML_FLOW_MAPPING_STYLE
+ || yaml_emitter_check_empty_mapping(emitter)) {
+ emitter->state = YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE;
+ }
+ else {
+ emitter->state = YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE;
+ }
+
+ return 1;
+}
+
+/*
+ * Check if the document content is an empty scalar.
+ */
+
+static int
+yaml_emitter_check_empty_document(yaml_emitter_t *emitter)
+{
+ return 0;
+}
+
+/*
+ * Check if the next events represent an empty sequence.
+ */
+
+static int
+yaml_emitter_check_empty_sequence(yaml_emitter_t *emitter)
+{
+ if (emitter->events.tail - emitter->events.head < 2)
+ return 0;
+
+ return (emitter->events.head[0].type == YAML_SEQUENCE_START_EVENT
+ && emitter->events.head[1].type == YAML_SEQUENCE_END_EVENT);
+}
+
+/*
+ * Check if the next events represent an empty mapping.
+ */
+
+static int
+yaml_emitter_check_empty_mapping(yaml_emitter_t *emitter)
+{
+ if (emitter->events.tail - emitter->events.head < 2)
+ return 0;
+
+ return (emitter->events.head[0].type == YAML_MAPPING_START_EVENT
+ && emitter->events.head[1].type == YAML_MAPPING_END_EVENT);
+}
+
+/*
+ * Check if the next node can be expressed as a simple key.
+ */
+
+static int
+yaml_emitter_check_simple_key(yaml_emitter_t *emitter)
+{
+ yaml_event_t *event = emitter->events.head;
+ size_t length = 0;
+
+ switch (event->type)
+ {
+ case YAML_ALIAS_EVENT:
+ length += emitter->anchor_data.anchor_length;
+ break;
+
+ case YAML_SCALAR_EVENT:
+ if (emitter->scalar_data.multiline)
+ return 0;
+ length += emitter->anchor_data.anchor_length
+ + emitter->tag_data.handle_length
+ + emitter->tag_data.suffix_length
+ + emitter->scalar_data.length;
+ break;
+
+ case YAML_SEQUENCE_START_EVENT:
+ if (!yaml_emitter_check_empty_sequence(emitter))
+ return 0;
+ length += emitter->anchor_data.anchor_length
+ + emitter->tag_data.handle_length
+ + emitter->tag_data.suffix_length;
+ break;
+
+ case YAML_MAPPING_START_EVENT:
+ if (!yaml_emitter_check_empty_mapping(emitter))
+ return 0;
+ length += emitter->anchor_data.anchor_length
+ + emitter->tag_data.handle_length
+ + emitter->tag_data.suffix_length;
+ break;
+
+ default:
+ return 0;
+ }
+
+ if (length > 128)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Determine an acceptable scalar style.
+ */
+
+static int
+yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event)
+{
+ yaml_scalar_style_t style = event->data.scalar.style;
+ int no_tag = (!emitter->tag_data.handle && !emitter->tag_data.suffix);
+
+ if (no_tag && !event->data.scalar.plain_implicit
+ && !event->data.scalar.quoted_implicit) {
+ return yaml_emitter_set_emitter_error(emitter,
+ "neither tag nor implicit flags are specified");
+ }
+
+ if (style == YAML_ANY_SCALAR_STYLE)
+ style = YAML_PLAIN_SCALAR_STYLE;
+
+ if (emitter->canonical)
+ style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
+
+ if (emitter->simple_key_context && emitter->scalar_data.multiline)
+ style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
+
+ if (style == YAML_PLAIN_SCALAR_STYLE)
+ {
+ if ((emitter->flow_level && !emitter->scalar_data.flow_plain_allowed)
+ || (!emitter->flow_level && !emitter->scalar_data.block_plain_allowed))
+ style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
+ if (!emitter->scalar_data.length
+ && (emitter->flow_level || emitter->simple_key_context))
+ style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
+ if (no_tag && !event->data.scalar.plain_implicit)
+ style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
+ }
+
+ if (style == YAML_SINGLE_QUOTED_SCALAR_STYLE)
+ {
+ if (!emitter->scalar_data.single_quoted_allowed)
+ style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
+ }
+
+ if (style == YAML_LITERAL_SCALAR_STYLE || style == YAML_FOLDED_SCALAR_STYLE)
+ {
+ if (!emitter->scalar_data.block_allowed
+ || emitter->flow_level || emitter->simple_key_context)
+ style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
+ }
+
+ if (no_tag && !event->data.scalar.quoted_implicit
+ && style != YAML_PLAIN_SCALAR_STYLE)
+ {
+ emitter->tag_data.handle = (yaml_char_t *)"!";
+ emitter->tag_data.handle_length = 1;
+ }
+
+ emitter->scalar_data.style = style;
+
+ return 1;
+}
+
+/*
+ * Write an achor.
+ */
+
+static int
+yaml_emitter_process_anchor(yaml_emitter_t *emitter)
+{
+ if (!emitter->anchor_data.anchor)
+ return 1;
+
+ if (!yaml_emitter_write_indicator(emitter,
+ (emitter->anchor_data.alias ? "*" : "&"), 1, 0, 0))
+ return 0;
+
+ return yaml_emitter_write_anchor(emitter,
+ emitter->anchor_data.anchor, emitter->anchor_data.anchor_length);
+}
+
+/*
+ * Write a tag.
+ */
+
+static int
+yaml_emitter_process_tag(yaml_emitter_t *emitter)
+{
+ if (!emitter->tag_data.handle && !emitter->tag_data.suffix)
+ return 1;
+
+ if (emitter->tag_data.handle)
+ {
+ if (!yaml_emitter_write_tag_handle(emitter, emitter->tag_data.handle,
+ emitter->tag_data.handle_length))
+ return 0;
+ if (emitter->tag_data.suffix) {
+ if (!yaml_emitter_write_tag_content(emitter, emitter->tag_data.suffix,
+ emitter->tag_data.suffix_length, 0))
+ return 0;
+ }
+ }
+ else
+ {
+ if (!yaml_emitter_write_indicator(emitter, "!<", 1, 0, 0))
+ return 0;
+ if (!yaml_emitter_write_tag_content(emitter, emitter->tag_data.suffix,
+ emitter->tag_data.suffix_length, 0))
+ return 0;
+ if (!yaml_emitter_write_indicator(emitter, ">", 0, 0, 0))
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Write a scalar.
+ */
+
+static int
+yaml_emitter_process_scalar(yaml_emitter_t *emitter)
+{
+ switch (emitter->scalar_data.style)
+ {
+ case YAML_PLAIN_SCALAR_STYLE:
+ return yaml_emitter_write_plain_scalar(emitter,
+ emitter->scalar_data.value, emitter->scalar_data.length,
+ !emitter->simple_key_context);
+
+ case YAML_SINGLE_QUOTED_SCALAR_STYLE:
+ return yaml_emitter_write_single_quoted_scalar(emitter,
+ emitter->scalar_data.value, emitter->scalar_data.length,
+ !emitter->simple_key_context);
+
+ case YAML_DOUBLE_QUOTED_SCALAR_STYLE:
+ return yaml_emitter_write_double_quoted_scalar(emitter,
+ emitter->scalar_data.value, emitter->scalar_data.length,
+ !emitter->simple_key_context);
+
+ case YAML_LITERAL_SCALAR_STYLE:
+ return yaml_emitter_write_literal_scalar(emitter,
+ emitter->scalar_data.value, emitter->scalar_data.length);
+
+ case YAML_FOLDED_SCALAR_STYLE:
+ return yaml_emitter_write_folded_scalar(emitter,
+ emitter->scalar_data.value, emitter->scalar_data.length);
+
+ default:
+ assert(1); /* Impossible. */
+ }
+
+ return 0;
+}
+
+/*
+ * Check if a %YAML directive is valid.
+ */
+
+static int
+yaml_emitter_analyze_titleVersion_directive(yaml_emitter_t *emitter,
+ yaml_titleVersion_directive_t titleVersion_directive)
+{
+ if (titleVersion_directive.major != 1 || titleVersion_directive.minor != 1) {
+ return yaml_emitter_set_emitter_error(emitter,
+ "incompatible %YAML directive");
+ }
+
+ return 1;
+}
+
+/*
+ * Check if a %TAG directive is valid.
+ */
+
+static int
+yaml_emitter_analyze_tag_directive(yaml_emitter_t *emitter,
+ yaml_tag_directive_t tag_directive)
+{
+ yaml_string_t handle;
+ yaml_string_t prefix;
+ size_t handle_length;
+ size_t prefix_length;
+
+ handle_length = strlen((char *)tag_directive.handle);
+ prefix_length = strlen((char *)tag_directive.prefix);
+ STRING_ASSIGN(handle, tag_directive.handle, handle_length);
+ STRING_ASSIGN(prefix, tag_directive.prefix, prefix_length);
+
+ if (handle.start == handle.end) {
+ return yaml_emitter_set_emitter_error(emitter,
+ "tag handle must not be empty");
+ }
+
+ if (handle.start[0] != '!') {
+ return yaml_emitter_set_emitter_error(emitter,
+ "tag handle must start with '!'");
+ }
+
+ if (handle.end[-1] != '!') {
+ return yaml_emitter_set_emitter_error(emitter,
+ "tag handle must end with '!'");
+ }
+
+ handle.pointer ++;
+
+ while (handle.pointer < handle.end-1) {
+ if (!IS_ALPHA(handle)) {
+ return yaml_emitter_set_emitter_error(emitter,
+ "tag handle must contain alphanumerical characters only");
+ }
+ MOVE(handle);
+ }
+
+ if (prefix.start == prefix.end) {
+ return yaml_emitter_set_emitter_error(emitter,
+ "tag prefix must not be empty");
+ }
+
+ return 1;
+}
+
+/*
+ * Check if an anchor is valid.
+ */
+
+static int
+yaml_emitter_analyze_anchor(yaml_emitter_t *emitter,
+ yaml_char_t *anchor, int alias)
+{
+ size_t anchor_length;
+ yaml_string_t string;
+
+ anchor_length = strlen((char *)anchor);
+ STRING_ASSIGN(string, anchor, anchor_length);
+
+ if (string.start == string.end) {
+ return yaml_emitter_set_emitter_error(emitter, alias ?
+ "alias value must not be empty" :
+ "anchor value must not be empty");
+ }
+
+ while (string.pointer != string.end) {
+ if (!IS_ALPHA(string)) {
+ return yaml_emitter_set_emitter_error(emitter, alias ?
+ "alias value must contain alphanumerical characters only" :
+ "anchor value must contain alphanumerical characters only");
+ }
+ MOVE(string);
+ }
+
+ emitter->anchor_data.anchor = string.start;
+ emitter->anchor_data.anchor_length = string.end - string.start;
+ emitter->anchor_data.alias = alias;
+
+ return 1;
+}
+
+/*
+ * Check if a tag is valid.
+ */
+
+static int
+yaml_emitter_analyze_tag(yaml_emitter_t *emitter,
+ yaml_char_t *tag)
+{
+ size_t tag_length;
+ yaml_string_t string;
+ yaml_tag_directive_t *tag_directive;
+
+ tag_length = strlen((char *)tag);
+ STRING_ASSIGN(string, tag, tag_length);
+
+ if (string.start == string.end) {
+ return yaml_emitter_set_emitter_error(emitter,
+ "tag value must not be empty");
+ }
+
+ for (tag_directive = emitter->tag_directives.start;
+ tag_directive != emitter->tag_directives.top; tag_directive ++) {
+ size_t prefix_length = strlen((char *)tag_directive->prefix);
+ if (prefix_length < (size_t)(string.end - string.start)
+ && strncmp((char *)tag_directive->prefix, (char *)string.start,
+ prefix_length) == 0)
+ {
+ emitter->tag_data.handle = tag_directive->handle;
+ emitter->tag_data.handle_length =
+ strlen((char *)tag_directive->handle);
+ emitter->tag_data.suffix = string.start + prefix_length;
+ emitter->tag_data.suffix_length =
+ (string.end - string.start) - prefix_length;
+ return 1;
+ }
+ }
+
+ emitter->tag_data.suffix = string.start;
+ emitter->tag_data.suffix_length = string.end - string.start;
+
+ return 1;
+}
+
+/*
+ * Check if a scalar is valid.
+ */
+
+static int
+yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length)
+{
+ yaml_string_t string;
+
+ int block_indicators = 0;
+ int flow_indicators = 0;
+ int line_breaks = 0;
+ int special_characters = 0;
+
+ int leading_space = 0;
+ int leading_break = 0;
+ int trailing_space = 0;
+ int trailing_break = 0;
+ int break_space = 0;
+ int space_break = 0;
+
+ int preceeded_by_whitespace = 0;
+ int followed_by_whitespace = 0;
+ int previous_space = 0;
+ int previous_break = 0;
+
+ STRING_ASSIGN(string, value, length);
+
+ emitter->scalar_data.value = value;
+ emitter->scalar_data.length = length;
+
+ if (string.start == string.end)
+ {
+ emitter->scalar_data.multiline = 0;
+ emitter->scalar_data.flow_plain_allowed = 0;
+ emitter->scalar_data.block_plain_allowed = 1;
+ emitter->scalar_data.single_quoted_allowed = 1;
+ emitter->scalar_data.block_allowed = 0;
+
+ return 1;
+ }
+
+ if ((CHECK_AT(string, '-', 0)
+ && CHECK_AT(string, '-', 1)
+ && CHECK_AT(string, '-', 2))
+ || (CHECK_AT(string, '.', 0)
+ && CHECK_AT(string, '.', 1)
+ && CHECK_AT(string, '.', 2))) {
+ block_indicators = 1;
+ flow_indicators = 1;
+ }
+
+ preceeded_by_whitespace = 1;
+ followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string));
+
+ while (string.pointer != string.end)
+ {
+ if (string.start == string.pointer)
+ {
+ if (CHECK(string, '#') || CHECK(string, ',')
+ || CHECK(string, '[') || CHECK(string, ']')
+ || CHECK(string, '{') || CHECK(string, '}')
+ || CHECK(string, '&') || CHECK(string, '*')
+ || CHECK(string, '!') || CHECK(string, '|')
+ || CHECK(string, '>') || CHECK(string, '\'')
+ || CHECK(string, '"') || CHECK(string, '%')
+ || CHECK(string, '@') || CHECK(string, '`')) {
+ flow_indicators = 1;
+ block_indicators = 1;
+ }
+
+ if (CHECK(string, '?') || CHECK(string, ':')) {
+ flow_indicators = 1;
+ if (followed_by_whitespace) {
+ block_indicators = 1;
+ }
+ }
+
+ if (CHECK(string, '-') && followed_by_whitespace) {
+ flow_indicators = 1;
+ block_indicators = 1;
+ }
+ }
+ else
+ {
+ if (CHECK(string, ',') || CHECK(string, '?')
+ || CHECK(string, '[') || CHECK(string, ']')
+ || CHECK(string, '{') || CHECK(string, '}')) {
+ flow_indicators = 1;
+ }
+
+ if (CHECK(string, ':')) {
+ flow_indicators = 1;
+ if (followed_by_whitespace) {
+ block_indicators = 1;
+ }
+ }
+
+ if (CHECK(string, '#') && preceeded_by_whitespace) {
+ flow_indicators = 1;
+ block_indicators = 1;
+ }
+ }
+
+ if (!IS_PRINTABLE(string)
+ || (!IS_ASCII(string) && !emitter->unicode)) {
+ special_characters = 1;
+ }
+
+ if (IS_BREAK(string)) {
+ line_breaks = 1;
+ }
+
+ if (IS_SPACE(string))
+ {
+ if (string.start == string.pointer) {
+ leading_space = 1;
+ }
+ if (string.pointer+WIDTH(string) == string.end) {
+ trailing_space = 1;
+ }
+ if (previous_break) {
+ break_space = 1;
+ }
+ previous_space = 1;
+ previous_break = 0;
+ }
+ else if (IS_BREAK(string))
+ {
+ if (string.start == string.pointer) {
+ leading_break = 1;
+ }
+ if (string.pointer+WIDTH(string) == string.end) {
+ trailing_break = 1;
+ }
+ if (previous_space) {
+ space_break = 1;
+ }
+ previous_space = 0;
+ previous_break = 1;
+ }
+ else
+ {
+ previous_space = 0;
+ previous_break = 0;
+ }
+
+ preceeded_by_whitespace = IS_BLANKZ(string);
+ MOVE(string);
+ if (string.pointer != string.end) {
+ followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string));
+ }
+ }
+
+ emitter->scalar_data.multiline = line_breaks;
+
+ emitter->scalar_data.flow_plain_allowed = 1;
+ emitter->scalar_data.block_plain_allowed = 1;
+ emitter->scalar_data.single_quoted_allowed = 1;
+ emitter->scalar_data.block_allowed = 1;
+
+ if (leading_space || leading_break || trailing_space || trailing_break) {
+ emitter->scalar_data.flow_plain_allowed = 0;
+ emitter->scalar_data.block_plain_allowed = 0;
+ }
+
+ if (trailing_space) {
+ emitter->scalar_data.block_allowed = 0;
+ }
+
+ if (break_space) {
+ emitter->scalar_data.flow_plain_allowed = 0;
+ emitter->scalar_data.block_plain_allowed = 0;
+ emitter->scalar_data.single_quoted_allowed = 0;
+ }
+
+ if (space_break || special_characters) {
+ emitter->scalar_data.flow_plain_allowed = 0;
+ emitter->scalar_data.block_plain_allowed = 0;
+ emitter->scalar_data.single_quoted_allowed = 0;
+ emitter->scalar_data.block_allowed = 0;
+ }
+
+ if (line_breaks) {
+ emitter->scalar_data.flow_plain_allowed = 0;
+ emitter->scalar_data.block_plain_allowed = 0;
+ }
+
+ if (flow_indicators) {
+ emitter->scalar_data.flow_plain_allowed = 0;
+ }
+
+ if (block_indicators) {
+ emitter->scalar_data.block_plain_allowed = 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Check if the event data is valid.
+ */
+
+static int
+yaml_emitter_analyze_event(yaml_emitter_t *emitter,
+ yaml_event_t *event)
+{
+ emitter->anchor_data.anchor = NULL;
+ emitter->anchor_data.anchor_length = 0;
+ emitter->tag_data.handle = NULL;
+ emitter->tag_data.handle_length = 0;
+ emitter->tag_data.suffix = NULL;
+ emitter->tag_data.suffix_length = 0;
+ emitter->scalar_data.value = NULL;
+ emitter->scalar_data.length = 0;
+
+ switch (event->type)
+ {
+ case YAML_ALIAS_EVENT:
+ if (!yaml_emitter_analyze_anchor(emitter,
+ event->data.alias.anchor, 1))
+ return 0;
+ return 1;
+
+ case YAML_SCALAR_EVENT:
+ if (event->data.scalar.anchor) {
+ if (!yaml_emitter_analyze_anchor(emitter,
+ event->data.scalar.anchor, 0))
+ return 0;
+ }
+ if (event->data.scalar.tag && (emitter->canonical ||
+ (!event->data.scalar.plain_implicit
+ && !event->data.scalar.quoted_implicit))) {
+ if (!yaml_emitter_analyze_tag(emitter, event->data.scalar.tag))
+ return 0;
+ }
+ if (!yaml_emitter_analyze_scalar(emitter,
+ event->data.scalar.value, event->data.scalar.length))
+ return 0;
+ return 1;
+
+ case YAML_SEQUENCE_START_EVENT:
+ if (event->data.sequence_start.anchor) {
+ if (!yaml_emitter_analyze_anchor(emitter,
+ event->data.sequence_start.anchor, 0))
+ return 0;
+ }
+ if (event->data.sequence_start.tag && (emitter->canonical ||
+ !event->data.sequence_start.implicit)) {
+ if (!yaml_emitter_analyze_tag(emitter,
+ event->data.sequence_start.tag))
+ return 0;
+ }
+ return 1;
+
+ case YAML_MAPPING_START_EVENT:
+ if (event->data.mapping_start.anchor) {
+ if (!yaml_emitter_analyze_anchor(emitter,
+ event->data.mapping_start.anchor, 0))
+ return 0;
+ }
+ if (event->data.mapping_start.tag && (emitter->canonical ||
+ !event->data.mapping_start.implicit)) {
+ if (!yaml_emitter_analyze_tag(emitter,
+ event->data.mapping_start.tag))
+ return 0;
+ }
+ return 1;
+
+ default:
+ return 1;
+ }
+}
+
+/*
+ * Write the BOM character.
+ */
+
+static int
+yaml_emitter_write_bom(yaml_emitter_t *emitter)
+{
+ if (!FLUSH(emitter)) return 0;
+
+ *(emitter->buffer.pointer++) = (yaml_char_t) '\xEF';
+ *(emitter->buffer.pointer++) = (yaml_char_t) '\xBB';
+ *(emitter->buffer.pointer++) = (yaml_char_t) '\xBF';
+
+ return 1;
+}
+
+static int
+yaml_emitter_write_indent(yaml_emitter_t *emitter)
+{
+ int indent = (emitter->indent >= 0) ? emitter->indent : 0;
+
+ if (!emitter->indention || emitter->column > indent
+ || (emitter->column == indent && !emitter->whitespace)) {
+ if (!PUT_BREAK(emitter)) return 0;
+ }
+
+ while (emitter->column < indent) {
+ if (!PUT(emitter, ' ')) return 0;
+ }
+
+ emitter->whitespace = 1;
+ emitter->indention = 1;
+
+ return 1;
+}
+
+static int
+yaml_emitter_write_indicator(yaml_emitter_t *emitter,
+ char *indicator, int need_whitespace,
+ int is_whitespace, int is_indention)
+{
+ size_t indicator_length;
+ yaml_string_t string;
+
+ indicator_length = strlen(indicator);
+ STRING_ASSIGN(string, (yaml_char_t *)indicator, indicator_length);
+
+ if (need_whitespace && !emitter->whitespace) {
+ if (!PUT(emitter, ' ')) return 0;
+ }
+
+ while (string.pointer != string.end) {
+ if (!WRITE(emitter, string)) return 0;
+ }
+
+ emitter->whitespace = is_whitespace;
+ emitter->indention = (emitter->indention && is_indention);
+ emitter->open_ended = 0;
+
+ return 1;
+}
+
+static int
+yaml_emitter_write_anchor(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length)
+{
+ yaml_string_t string;
+ STRING_ASSIGN(string, value, length);
+
+ while (string.pointer != string.end) {
+ if (!WRITE(emitter, string)) return 0;
+ }
+
+ emitter->whitespace = 0;
+ emitter->indention = 0;
+
+ return 1;
+}
+
+static int
+yaml_emitter_write_tag_handle(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length)
+{
+ yaml_string_t string;
+ STRING_ASSIGN(string, value, length);
+
+ if (!emitter->whitespace) {
+ if (!PUT(emitter, ' ')) return 0;
+ }
+
+ while (string.pointer != string.end) {
+ if (!WRITE(emitter, string)) return 0;
+ }
+
+ emitter->whitespace = 0;
+ emitter->indention = 0;
+
+ return 1;
+}
+
+static int
+yaml_emitter_write_tag_content(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length,
+ int need_whitespace)
+{
+ yaml_string_t string;
+ STRING_ASSIGN(string, value, length);
+
+ if (need_whitespace && !emitter->whitespace) {
+ if (!PUT(emitter, ' ')) return 0;
+ }
+
+ while (string.pointer != string.end) {
+ if (IS_ALPHA(string)
+ || CHECK(string, ';') || CHECK(string, '/')
+ || CHECK(string, '?') || CHECK(string, ':')
+ || CHECK(string, '@') || CHECK(string, '&')
+ || CHECK(string, '=') || CHECK(string, '+')
+ || CHECK(string, '$') || CHECK(string, ',')
+ || CHECK(string, '_') || CHECK(string, '.')
+ || CHECK(string, '~') || CHECK(string, '*')
+ || CHECK(string, '\'') || CHECK(string, '(')
+ || CHECK(string, ')') || CHECK(string, '[')
+ || CHECK(string, ']')) {
+ if (!WRITE(emitter, string)) return 0;
+ }
+ else {
+ int width = WIDTH(string);
+ unsigned int value;
+ while (width --) {
+ value = *(string.pointer++);
+ if (!PUT(emitter, '%')) return 0;
+ if (!PUT(emitter, (value >> 4)
+ + ((value >> 4) < 10 ? '0' : 'A' - 10)))
+ return 0;
+ if (!PUT(emitter, (value & 0x0F)
+ + ((value & 0x0F) < 10 ? '0' : 'A' - 10)))
+ return 0;
+ }
+ }
+ }
+
+ emitter->whitespace = 0;
+ emitter->indention = 0;
+
+ return 1;
+}
+
+static int
+yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length, int allow_breaks)
+{
+ yaml_string_t string;
+ int spaces = 0;
+ int breaks = 0;
+
+ STRING_ASSIGN(string, value, length);
+
+ if (!emitter->whitespace) {
+ if (!PUT(emitter, ' ')) return 0;
+ }
+
+ while (string.pointer != string.end)
+ {
+ if (IS_SPACE(string))
+ {
+ if (allow_breaks && !spaces
+ && emitter->column > emitter->best_width
+ && !IS_SPACE_AT(string, 1)) {
+ if (!yaml_emitter_write_indent(emitter)) return 0;
+ MOVE(string);
+ }
+ else {
+ if (!WRITE(emitter, string)) return 0;
+ }
+ spaces = 1;
+ }
+ else if (IS_BREAK(string))
+ {
+ if (!breaks && CHECK(string, '\n')) {
+ if (!PUT_BREAK(emitter)) return 0;
+ }
+ if (!WRITE_BREAK(emitter, string)) return 0;
+ emitter->indention = 1;
+ breaks = 1;
+ }
+ else
+ {
+ if (breaks) {
+ if (!yaml_emitter_write_indent(emitter)) return 0;
+ }
+ if (!WRITE(emitter, string)) return 0;
+ emitter->indention = 0;
+ spaces = 0;
+ breaks = 0;
+ }
+ }
+
+ emitter->whitespace = 0;
+ emitter->indention = 0;
+ if (emitter->root_context)
+ {
+ emitter->open_ended = 1;
+ }
+
+ return 1;
+}
+
+static int
+yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length, int allow_breaks)
+{
+ yaml_string_t string;
+ int spaces = 0;
+ int breaks = 0;
+
+ STRING_ASSIGN(string, value, length);
+
+ if (!yaml_emitter_write_indicator(emitter, "'", 1, 0, 0))
+ return 0;
+
+ while (string.pointer != string.end)
+ {
+ if (IS_SPACE(string))
+ {
+ if (allow_breaks && !spaces
+ && emitter->column > emitter->best_width
+ && string.pointer != string.start
+ && string.pointer != string.end - 1
+ && !IS_SPACE_AT(string, 1)) {
+ if (!yaml_emitter_write_indent(emitter)) return 0;
+ MOVE(string);
+ }
+ else {
+ if (!WRITE(emitter, string)) return 0;
+ }
+ spaces = 1;
+ }
+ else if (IS_BREAK(string))
+ {
+ if (!breaks && CHECK(string, '\n')) {
+ if (!PUT_BREAK(emitter)) return 0;
+ }
+ if (!WRITE_BREAK(emitter, string)) return 0;
+ emitter->indention = 1;
+ breaks = 1;
+ }
+ else
+ {
+ if (breaks) {
+ if (!yaml_emitter_write_indent(emitter)) return 0;
+ }
+ if (CHECK(string, '\'')) {
+ if (!PUT(emitter, '\'')) return 0;
+ }
+ if (!WRITE(emitter, string)) return 0;
+ emitter->indention = 0;
+ spaces = 0;
+ breaks = 0;
+ }
+ }
+
+ if (!yaml_emitter_write_indicator(emitter, "'", 0, 0, 0))
+ return 0;
+
+ emitter->whitespace = 0;
+ emitter->indention = 0;
+
+ return 1;
+}
+
+static int
+yaml_emitter_write_double_quoted_scalar(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length, int allow_breaks)
+{
+ yaml_string_t string;
+ int spaces = 0;
+
+ STRING_ASSIGN(string, value, length);
+
+ if (!yaml_emitter_write_indicator(emitter, "\"", 1, 0, 0))
+ return 0;
+
+ while (string.pointer != string.end)
+ {
+ if (!IS_PRINTABLE(string) || (!emitter->unicode && !IS_ASCII(string))
+ || IS_BOM(string) || IS_BREAK(string)
+ || CHECK(string, '"') || CHECK(string, '\\'))
+ {
+ unsigned char octet;
+ unsigned int width;
+ unsigned int value;
+ int k;
+
+ octet = string.pointer[0];
+ width = (octet & 0x80) == 0x00 ? 1 :
+ (octet & 0xE0) == 0xC0 ? 2 :
+ (octet & 0xF0) == 0xE0 ? 3 :
+ (octet & 0xF8) == 0xF0 ? 4 : 0;
+ value = (octet & 0x80) == 0x00 ? octet & 0x7F :
+ (octet & 0xE0) == 0xC0 ? octet & 0x1F :
+ (octet & 0xF0) == 0xE0 ? octet & 0x0F :
+ (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
+ for (k = 1; k < (int)width; k ++) {
+ octet = string.pointer[k];
+ value = (value << 6) + (octet & 0x3F);
+ }
+ string.pointer += width;
+
+ if (!PUT(emitter, '\\')) return 0;
+
+ switch (value)
+ {
+ case 0x00:
+ if (!PUT(emitter, '0')) return 0;
+ break;
+
+ case 0x07:
+ if (!PUT(emitter, 'a')) return 0;
+ break;
+
+ case 0x08:
+ if (!PUT(emitter, 'b')) return 0;
+ break;
+
+ case 0x09:
+ if (!PUT(emitter, 't')) return 0;
+ break;
+
+ case 0x0A:
+ if (!PUT(emitter, 'n')) return 0;
+ break;
+
+ case 0x0B:
+ if (!PUT(emitter, 'v')) return 0;
+ break;
+
+ case 0x0C:
+ if (!PUT(emitter, 'f')) return 0;
+ break;
+
+ case 0x0D:
+ if (!PUT(emitter, 'r')) return 0;
+ break;
+
+ case 0x1B:
+ if (!PUT(emitter, 'e')) return 0;
+ break;
+
+ case 0x22:
+ if (!PUT(emitter, '\"')) return 0;
+ break;
+
+ case 0x5C:
+ if (!PUT(emitter, '\\')) return 0;
+ break;
+
+ case 0x85:
+ if (!PUT(emitter, 'N')) return 0;
+ break;
+
+ case 0xA0:
+ if (!PUT(emitter, '_')) return 0;
+ break;
+
+ case 0x2028:
+ if (!PUT(emitter, 'L')) return 0;
+ break;
+
+ case 0x2029:
+ if (!PUT(emitter, 'P')) return 0;
+ break;
+
+ default:
+ if (value <= 0xFF) {
+ if (!PUT(emitter, 'x')) return 0;
+ width = 2;
+ }
+ else if (value <= 0xFFFF) {
+ if (!PUT(emitter, 'u')) return 0;
+ width = 4;
+ }
+ else {
+ if (!PUT(emitter, 'U')) return 0;
+ width = 8;
+ }
+ for (k = (width-1)*4; k >= 0; k -= 4) {
+ int digit = (value >> k) & 0x0F;
+ if (!PUT(emitter, digit + (digit < 10 ? '0' : 'A'-10)))
+ return 0;
+ }
+ }
+ spaces = 0;
+ }
+ else if (IS_SPACE(string))
+ {
+ if (allow_breaks && !spaces
+ && emitter->column > emitter->best_width
+ && string.pointer != string.start
+ && string.pointer != string.end - 1) {
+ if (!yaml_emitter_write_indent(emitter)) return 0;
+ if (IS_SPACE_AT(string, 1)) {
+ if (!PUT(emitter, '\\')) return 0;
+ }
+ MOVE(string);
+ }
+ else {
+ if (!WRITE(emitter, string)) return 0;
+ }
+ spaces = 1;
+ }
+ else
+ {
+ if (!WRITE(emitter, string)) return 0;
+ spaces = 0;
+ }
+ }
+
+ if (!yaml_emitter_write_indicator(emitter, "\"", 0, 0, 0))
+ return 0;
+
+ emitter->whitespace = 0;
+ emitter->indention = 0;
+
+ return 1;
+}
+
+static int
+yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter,
+ yaml_string_t string)
+{
+ char indent_hint[2];
+ char *chomp_hint = NULL;
+
+ if (IS_SPACE(string) || IS_BREAK(string))
+ {
+ indent_hint[0] = '0' + (char)emitter->best_indent;
+ indent_hint[1] = '\0';
+ if (!yaml_emitter_write_indicator(emitter, indent_hint, 0, 0, 0))
+ return 0;
+ }
+
+ emitter->open_ended = 0;
+
+ string.pointer = string.end;
+ if (string.start == string.pointer)
+ {
+ chomp_hint = "-";
+ }
+ else
+ {
+ do {
+ string.pointer --;
+ } while ((*string.pointer & 0xC0) == 0x80);
+ if (!IS_BREAK(string))
+ {
+ chomp_hint = "-";
+ }
+ else if (string.start == string.pointer)
+ {
+ chomp_hint = "+";
+ emitter->open_ended = 1;
+ }
+ else
+ {
+ do {
+ string.pointer --;
+ } while ((*string.pointer & 0xC0) == 0x80);
+ if (IS_BREAK(string))
+ {
+ chomp_hint = "+";
+ emitter->open_ended = 1;
+ }
+ }
+ }
+
+ if (chomp_hint)
+ {
+ if (!yaml_emitter_write_indicator(emitter, chomp_hint, 0, 0, 0))
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length)
+{
+ yaml_string_t string;
+ int breaks = 1;
+
+ STRING_ASSIGN(string, value, length);
+
+ if (!yaml_emitter_write_indicator(emitter, "|", 1, 0, 0))
+ return 0;
+ if (!yaml_emitter_write_block_scalar_hints(emitter, string))
+ return 0;
+ if (!PUT_BREAK(emitter)) return 0;
+ emitter->indention = 1;
+ emitter->whitespace = 1;
+
+ while (string.pointer != string.end)
+ {
+ if (IS_BREAK(string))
+ {
+ if (!WRITE_BREAK(emitter, string)) return 0;
+ emitter->indention = 1;
+ breaks = 1;
+ }
+ else
+ {
+ if (breaks) {
+ if (!yaml_emitter_write_indent(emitter)) return 0;
+ }
+ if (!WRITE(emitter, string)) return 0;
+ emitter->indention = 0;
+ breaks = 0;
+ }
+ }
+
+ return 1;
+}
+
+static int
+yaml_emitter_write_folded_scalar(yaml_emitter_t *emitter,
+ yaml_char_t *value, size_t length)
+{
+ yaml_string_t string;
+ int breaks = 1;
+ int leading_spaces = 1;
+
+ STRING_ASSIGN(string, value, length);
+
+ if (!yaml_emitter_write_indicator(emitter, ">", 1, 0, 0))
+ return 0;
+ if (!yaml_emitter_write_block_scalar_hints(emitter, string))
+ return 0;
+ if (!PUT_BREAK(emitter)) return 0;
+ emitter->indention = 1;
+ emitter->whitespace = 1;
+
+ while (string.pointer != string.end)
+ {
+ if (IS_BREAK(string))
+ {
+ if (!breaks && !leading_spaces && CHECK(string, '\n')) {
+ int k = 0;
+ while (IS_BREAK_AT(string, k)) {
+ k += WIDTH_AT(string, k);
+ }
+ if (!IS_BLANKZ_AT(string, k)) {
+ if (!PUT_BREAK(emitter)) return 0;
+ }
+ }
+ if (!WRITE_BREAK(emitter, string)) return 0;
+ emitter->indention = 1;
+ breaks = 1;
+ }
+ else
+ {
+ if (breaks) {
+ if (!yaml_emitter_write_indent(emitter)) return 0;
+ leading_spaces = IS_BLANK(string);
+ }
+ if (!breaks && IS_SPACE(string) && !IS_SPACE_AT(string, 1)
+ && emitter->column > emitter->best_width) {
+ if (!yaml_emitter_write_indent(emitter)) return 0;
+ MOVE(string);
+ }
+ else {
+ if (!WRITE(emitter, string)) return 0;
+ }
+ emitter->indention = 0;
+ breaks = 0;
+ }
+ }
+
+ return 1;
+}
+
diff --git a/libyaml/loader.c b/libyaml/loader.c
new file mode 100644
index 0000000..b3bdf25
--- /dev/null
+++ b/libyaml/loader.c
@@ -0,0 +1,432 @@
+
+#include "libyaml/yaml_private.h"
+
+/*
+ * API functions.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);
+
+/*
+ * Error handling.
+ */
+
+static int
+yaml_parser_set_composer_error(yaml_parser_t *parser,
+ const char *problem, yaml_mark_t problem_mark);
+
+static int
+yaml_parser_set_composer_error_context(yaml_parser_t *parser,
+ const char *context, yaml_mark_t context_mark,
+ const char *problem, yaml_mark_t problem_mark);
+
+
+/*
+ * Alias handling.
+ */
+
+static int
+yaml_parser_register_anchor(yaml_parser_t *parser,
+ int index, yaml_char_t *anchor);
+
+/*
+ * Clean up functions.
+ */
+
+static void
+yaml_parser_delete_aliases(yaml_parser_t *parser);
+
+/*
+ * Composer functions.
+ */
+
+static int
+yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event);
+
+static int
+yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event);
+
+static int
+yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event);
+
+static int
+yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event);
+
+static int
+yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event);
+
+static int
+yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event);
+
+/*
+ * Load the next document of the stream.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document)
+{
+ yaml_event_t event;
+
+ assert(parser); /* Non-NULL parser object is expected. */
+ assert(document); /* Non-NULL document object is expected. */
+
+ memset(document, 0, sizeof(yaml_document_t));
+ if (!STACK_INIT(parser, document->nodes, INITIAL_STACK_SIZE))
+ goto error;
+
+ if (!parser->stream_start_produced) {
+ if (!yaml_parser_parse(parser, &event)) goto error;
+ assert(event.type == YAML_STREAM_START_EVENT);
+ /* STREAM-START is expected. */
+ }
+
+ if (parser->stream_end_produced) {
+ return 1;
+ }
+
+ if (!yaml_parser_parse(parser, &event)) goto error;
+ if (event.type == YAML_STREAM_END_EVENT) {
+ return 1;
+ }
+
+ if (!STACK_INIT(parser, parser->aliases, INITIAL_STACK_SIZE))
+ goto error;
+
+ parser->document = document;
+
+ if (!yaml_parser_load_document(parser, &event)) goto error;
+
+ yaml_parser_delete_aliases(parser);
+ parser->document = NULL;
+
+ return 1;
+
+error:
+
+ yaml_parser_delete_aliases(parser);
+ yaml_document_delete(document);
+ parser->document = NULL;
+
+ return 0;
+}
+
+/*
+ * Set composer error.
+ */
+
+static int
+yaml_parser_set_composer_error(yaml_parser_t *parser,
+ const char *problem, yaml_mark_t problem_mark)
+{
+ parser->error = YAML_COMPOSER_ERROR;
+ parser->problem = problem;
+ parser->problem_mark = problem_mark;
+
+ return 0;
+}
+
+/*
+ * Set composer error with context.
+ */
+
+static int
+yaml_parser_set_composer_error_context(yaml_parser_t *parser,
+ const char *context, yaml_mark_t context_mark,
+ const char *problem, yaml_mark_t problem_mark)
+{
+ parser->error = YAML_COMPOSER_ERROR;
+ parser->context = context;
+ parser->context_mark = context_mark;
+ parser->problem = problem;
+ parser->problem_mark = problem_mark;
+
+ return 0;
+}
+
+/*
+ * Delete the stack of aliases.
+ */
+
+static void
+yaml_parser_delete_aliases(yaml_parser_t *parser)
+{
+ while (!STACK_EMPTY(parser, parser->aliases)) {
+ yaml_free(POP(parser, parser->aliases).anchor);
+ }
+ STACK_DEL(parser, parser->aliases);
+}
+
+/*
+ * Compose a document object.
+ */
+
+static int
+yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event)
+{
+ yaml_event_t event;
+
+ assert(first_event->type == YAML_DOCUMENT_START_EVENT);
+ /* DOCUMENT-START is expected. */
+
+ parser->document->titleVersion_directive
+ = first_event->data.document_start.titleVersion_directive;
+ parser->document->tag_directives.start
+ = first_event->data.document_start.tag_directives.start;
+ parser->document->tag_directives.end
+ = first_event->data.document_start.tag_directives.end;
+ parser->document->start_implicit
+ = first_event->data.document_start.implicit;
+ parser->document->start_mark = first_event->start_mark;
+
+ if (!yaml_parser_parse(parser, &event)) return 0;
+
+ if (!yaml_parser_load_node(parser, &event)) return 0;
+
+ if (!yaml_parser_parse(parser, &event)) return 0;
+ assert(event.type == YAML_DOCUMENT_END_EVENT);
+ /* DOCUMENT-END is expected. */
+
+ parser->document->end_implicit = event.data.document_end.implicit;
+ parser->document->end_mark = event.end_mark;
+
+ return 1;
+}
+
+/*
+ * Compose a node.
+ */
+
+static int
+yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event)
+{
+ switch (first_event->type) {
+ case YAML_ALIAS_EVENT:
+ return yaml_parser_load_alias(parser, first_event);
+ case YAML_SCALAR_EVENT:
+ return yaml_parser_load_scalar(parser, first_event);
+ case YAML_SEQUENCE_START_EVENT:
+ return yaml_parser_load_sequence(parser, first_event);
+ case YAML_MAPPING_START_EVENT:
+ return yaml_parser_load_mapping(parser, first_event);
+ default:
+ assert(0); /* Could not happen. */
+ return 0;
+ }
+
+ return 0;
+}
+
+/*
+ * Add an anchor.
+ */
+
+static int
+yaml_parser_register_anchor(yaml_parser_t *parser,
+ int index, yaml_char_t *anchor)
+{
+ yaml_alias_data_t data;
+ yaml_alias_data_t *alias_data;
+
+ if (!anchor) return 1;
+
+ data.anchor = anchor;
+ data.index = index;
+ data.mark = parser->document->nodes.start[index-1].start_mark;
+
+ for (alias_data = parser->aliases.start;
+ alias_data != parser->aliases.top; alias_data ++) {
+ if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
+ yaml_free(anchor);
+ return yaml_parser_set_composer_error_context(parser,
+ "found duplicate anchor; first occurence",
+ alias_data->mark, "second occurence", data.mark);
+ }
+ }
+
+ if (!PUSH(parser, parser->aliases, data)) {
+ yaml_free(anchor);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Compose a node corresponding to an alias.
+ */
+
+static int
+yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event)
+{
+ yaml_char_t *anchor = first_event->data.alias.anchor;
+ yaml_alias_data_t *alias_data;
+
+ for (alias_data = parser->aliases.start;
+ alias_data != parser->aliases.top; alias_data ++) {
+ if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
+ yaml_free(anchor);
+ return alias_data->index;
+ }
+ }
+
+ yaml_free(anchor);
+ return yaml_parser_set_composer_error(parser, "found undefined alias",
+ first_event->start_mark);
+}
+
+/*
+ * Compose a scalar node.
+ */
+
+static int
+yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event)
+{
+ yaml_node_t node;
+ int index;
+ yaml_char_t *tag = first_event->data.scalar.tag;
+
+ if (!tag || strcmp((char *)tag, "!") == 0) {
+ yaml_free(tag);
+ tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
+ if (!tag) goto error;
+ }
+
+ SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value,
+ first_event->data.scalar.length, first_event->data.scalar.style,
+ first_event->start_mark, first_event->end_mark);
+
+ if (!PUSH(parser, parser->document->nodes, node)) goto error;
+
+ index = parser->document->nodes.top - parser->document->nodes.start;
+
+ if (!yaml_parser_register_anchor(parser, index,
+ first_event->data.scalar.anchor)) return 0;
+
+ return index;
+
+error:
+ yaml_free(tag);
+ yaml_free(first_event->data.scalar.anchor);
+ yaml_free(first_event->data.scalar.value);
+ return 0;
+}
+
+/*
+ * Compose a sequence node.
+ */
+
+static int
+yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event)
+{
+ yaml_event_t event;
+ yaml_node_t node;
+ struct {
+ yaml_node_item_t *start;
+ yaml_node_item_t *end;
+ yaml_node_item_t *top;
+ } items = { NULL, NULL, NULL };
+ int index, item_index;
+ yaml_char_t *tag = first_event->data.sequence_start.tag;
+
+ if (!tag || strcmp((char *)tag, "!") == 0) {
+ yaml_free(tag);
+ tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
+ if (!tag) goto error;
+ }
+
+ if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error;
+
+ SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
+ first_event->data.sequence_start.style,
+ first_event->start_mark, first_event->end_mark);
+
+ if (!PUSH(parser, parser->document->nodes, node)) goto error;
+
+ index = parser->document->nodes.top - parser->document->nodes.start;
+
+ if (!yaml_parser_register_anchor(parser, index,
+ first_event->data.sequence_start.anchor)) return 0;
+
+ if (!yaml_parser_parse(parser, &event)) return 0;
+
+ while (event.type != YAML_SEQUENCE_END_EVENT) {
+ item_index = yaml_parser_load_node(parser, &event);
+ if (!item_index) return 0;
+ if (!PUSH(parser,
+ parser->document->nodes.start[index-1].data.sequence.items,
+ item_index)) return 0;
+ if (!yaml_parser_parse(parser, &event)) return 0;
+ }
+
+ parser->document->nodes.start[index-1].end_mark = event.end_mark;
+
+ return index;
+
+error:
+ yaml_free(tag);
+ yaml_free(first_event->data.sequence_start.anchor);
+ return 0;
+}
+
+/*
+ * Compose a mapping node.
+ */
+
+static int
+yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
+{
+ yaml_event_t event;
+ yaml_node_t node;
+ struct {
+ yaml_node_pair_t *start;
+ yaml_node_pair_t *end;
+ yaml_node_pair_t *top;
+ } pairs = { NULL, NULL, NULL };
+ int index;
+ yaml_node_pair_t pair;
+ yaml_char_t *tag = first_event->data.mapping_start.tag;
+
+ if (!tag || strcmp((char *)tag, "!") == 0) {
+ yaml_free(tag);
+ tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
+ if (!tag) goto error;
+ }
+
+ if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error;
+
+ MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
+ first_event->data.mapping_start.style,
+ first_event->start_mark, first_event->end_mark);
+
+ if (!PUSH(parser, parser->document->nodes, node)) goto error;
+
+ index = parser->document->nodes.top - parser->document->nodes.start;
+
+ if (!yaml_parser_register_anchor(parser, index,
+ first_event->data.mapping_start.anchor)) return 0;
+
+ if (!yaml_parser_parse(parser, &event)) return 0;
+
+ while (event.type != YAML_MAPPING_END_EVENT) {
+ pair.key = yaml_parser_load_node(parser, &event);
+ if (!pair.key) return 0;
+ if (!yaml_parser_parse(parser, &event)) return 0;
+ pair.value = yaml_parser_load_node(parser, &event);
+ if (!pair.value) return 0;
+ if (!PUSH(parser,
+ parser->document->nodes.start[index-1].data.mapping.pairs,
+ pair)) return 0;
+ if (!yaml_parser_parse(parser, &event)) return 0;
+ }
+
+ parser->document->nodes.start[index-1].end_mark = event.end_mark;
+
+ return index;
+
+error:
+ yaml_free(tag);
+ yaml_free(first_event->data.mapping_start.anchor);
+ return 0;
+}
+
diff --git a/libyaml/parser.c b/libyaml/parser.c
new file mode 100644
index 0000000..0649d85
--- /dev/null
+++ b/libyaml/parser.c
@@ -0,0 +1,1374 @@
+
+/*
+ * The parser implements the following grammar:
+ *
+ * stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+ * implicit_document ::= block_node DOCUMENT-END*
+ * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+ * block_node_or_indentless_sequence ::=
+ * ALIAS
+ * | properties (block_content | indentless_block_sequence)?
+ * | block_content
+ * | indentless_block_sequence
+ * block_node ::= ALIAS
+ * | properties block_content?
+ * | block_content
+ * flow_node ::= ALIAS
+ * | properties flow_content?
+ * | flow_content
+ * properties ::= TAG ANCHOR? | ANCHOR TAG?
+ * block_content ::= block_collection | flow_collection | SCALAR
+ * flow_content ::= flow_collection | SCALAR
+ * block_collection ::= block_sequence | block_mapping
+ * flow_collection ::= flow_sequence | flow_mapping
+ * block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+ * indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+ * block_mapping ::= BLOCK-MAPPING_START
+ * ((KEY block_node_or_indentless_sequence?)?
+ * (VALUE block_node_or_indentless_sequence?)?)*
+ * BLOCK-END
+ * flow_sequence ::= FLOW-SEQUENCE-START
+ * (flow_sequence_entry FLOW-ENTRY)*
+ * flow_sequence_entry?
+ * FLOW-SEQUENCE-END
+ * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+ * flow_mapping ::= FLOW-MAPPING-START
+ * (flow_mapping_entry FLOW-ENTRY)*
+ * flow_mapping_entry?
+ * FLOW-MAPPING-END
+ * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+ */
+
+#include "libyaml/yaml_private.h"
+
+/*
+ * Peek the next token in the token queue.
+ */
+
+#define PEEK_TOKEN(parser) \
+ ((parser->token_available || yaml_parser_fetch_more_tokens(parser)) ? \
+ parser->tokens.head : NULL)
+
+/*
+ * Remove the next token from the queue (must be called after PEEK_TOKEN).
+ */
+
+#define SKIP_TOKEN(parser) \
+ (parser->token_available = 0, \
+ parser->tokens_parsed ++, \
+ parser->stream_end_produced = \
+ (parser->tokens.head->type == YAML_STREAM_END_TOKEN), \
+ parser->tokens.head ++)
+
+/*
+ * Public API declarations.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event);
+
+/*
+ * Error handling.
+ */
+
+static int
+yaml_parser_set_parser_error(yaml_parser_t *parser,
+ const char *problem, yaml_mark_t problem_mark);
+
+static int
+yaml_parser_set_parser_error_context(yaml_parser_t *parser,
+ const char *context, yaml_mark_t context_mark,
+ const char *problem, yaml_mark_t problem_mark);
+
+/*
+ * State functions.
+ */
+
+static int
+yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event);
+
+static int
+yaml_parser_parse_stream_start(yaml_parser_t *parser, yaml_event_t *event);
+
+static int
+yaml_parser_parse_document_start(yaml_parser_t *parser, yaml_event_t *event,
+ int implicit);
+
+static int
+yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event);
+
+static int
+yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event);
+
+static int
+yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event,
+ int block, int indentless_sequence);
+
+static int
+yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser,
+ yaml_event_t *event, int first);
+
+static int
+yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser,
+ yaml_event_t *event);
+
+static int
+yaml_parser_parse_block_mapping_key(yaml_parser_t *parser,
+ yaml_event_t *event, int first);
+
+static int
+yaml_parser_parse_block_mapping_value(yaml_parser_t *parser,
+ yaml_event_t *event);
+
+static int
+yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser,
+ yaml_event_t *event, int first);
+
+static int
+yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser,
+ yaml_event_t *event);
+
+static int
+yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser,
+ yaml_event_t *event);
+
+static int
+yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser,
+ yaml_event_t *event);
+
+static int
+yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser,
+ yaml_event_t *event, int first);
+
+static int
+yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser,
+ yaml_event_t *event, int empty);
+
+/*
+ * Utility functions.
+ */
+
+static int
+yaml_parser_process_empty_scalar(yaml_parser_t *parser,
+ yaml_event_t *event, yaml_mark_t mark);
+
+static int
+yaml_parser_process_directives(yaml_parser_t *parser,
+ yaml_titleVersion_directive_t **titleVersion_directive_ref,
+ yaml_tag_directive_t **tag_directives_start_ref,
+ yaml_tag_directive_t **tag_directives_end_ref);
+
+static int
+yaml_parser_append_tag_directive(yaml_parser_t *parser,
+ yaml_tag_directive_t value, int allow_duplicates, yaml_mark_t mark);
+
+/*
+ * Get the next event.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event)
+{
+ assert(parser); /* Non-NULL parser object is expected. */
+ assert(event); /* Non-NULL event object is expected. */
+
+ /* Erase the event object. */
+
+ memset(event, 0, sizeof(yaml_event_t));
+
+ /* No events after the end of the stream or error. */
+
+ if (parser->stream_end_produced || parser->error ||
+ parser->state == YAML_PARSE_END_STATE) {
+ return 1;
+ }
+
+ /* Generate the next event. */
+
+ return yaml_parser_state_machine(parser, event);
+}
+
+/*
+ * Set parser error.
+ */
+
+static int
+yaml_parser_set_parser_error(yaml_parser_t *parser,
+ const char *problem, yaml_mark_t problem_mark)
+{
+ parser->error = YAML_PARSER_ERROR;
+ parser->problem = problem;
+ parser->problem_mark = problem_mark;
+
+ return 0;
+}
+
+static int
+yaml_parser_set_parser_error_context(yaml_parser_t *parser,
+ const char *context, yaml_mark_t context_mark,
+ const char *problem, yaml_mark_t problem_mark)
+{
+ parser->error = YAML_PARSER_ERROR;
+ parser->context = context;
+ parser->context_mark = context_mark;
+ parser->problem = problem;
+ parser->problem_mark = problem_mark;
+
+ return 0;
+}
+
+
+/*
+ * State dispatcher.
+ */
+
+static int
+yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event)
+{
+ switch (parser->state)
+ {
+ case YAML_PARSE_STREAM_START_STATE:
+ return yaml_parser_parse_stream_start(parser, event);
+
+ case YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE:
+ return yaml_parser_parse_document_start(parser, event, 1);
+
+ case YAML_PARSE_DOCUMENT_START_STATE:
+ return yaml_parser_parse_document_start(parser, event, 0);
+
+ case YAML_PARSE_DOCUMENT_CONTENT_STATE:
+ return yaml_parser_parse_document_content(parser, event);
+
+ case YAML_PARSE_DOCUMENT_END_STATE:
+ return yaml_parser_parse_document_end(parser, event);
+
+ case YAML_PARSE_BLOCK_NODE_STATE:
+ return yaml_parser_parse_node(parser, event, 1, 0);
+
+ case YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
+ return yaml_parser_parse_node(parser, event, 1, 1);
+
+ case YAML_PARSE_FLOW_NODE_STATE:
+ return yaml_parser_parse_node(parser, event, 0, 0);
+
+ case YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+ return yaml_parser_parse_block_sequence_entry(parser, event, 1);
+
+ case YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_block_sequence_entry(parser, event, 0);
+
+ case YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_indentless_sequence_entry(parser, event);
+
+ case YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return yaml_parser_parse_block_mapping_key(parser, event, 1);
+
+ case YAML_PARSE_BLOCK_MAPPING_KEY_STATE:
+ return yaml_parser_parse_block_mapping_key(parser, event, 0);
+
+ case YAML_PARSE_BLOCK_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_block_mapping_value(parser, event);
+
+ case YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+ return yaml_parser_parse_flow_sequence_entry(parser, event, 1);
+
+ case YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_flow_sequence_entry(parser, event, 0);
+
+ case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event);
+
+ case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event);
+
+ case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event);
+
+ case YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+ return yaml_parser_parse_flow_mapping_key(parser, event, 1);
+
+ case YAML_PARSE_FLOW_MAPPING_KEY_STATE:
+ return yaml_parser_parse_flow_mapping_key(parser, event, 0);
+
+ case YAML_PARSE_FLOW_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_flow_mapping_value(parser, event, 0);
+
+ case YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+ return yaml_parser_parse_flow_mapping_value(parser, event, 1);
+
+ default:
+ assert(1); /* Invalid state. */
+ }
+
+ return 0;
+}
+
+/*
+ * Parse the production:
+ * stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+ * ************
+ */
+
+static int
+yaml_parser_parse_stream_start(yaml_parser_t *parser, yaml_event_t *event)
+{
+ yaml_token_t *token;
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ if (token->type != YAML_STREAM_START_TOKEN) {
+ return yaml_parser_set_parser_error(parser,
+ "did not find expected ", token->start_mark);
+ }
+
+ parser->state = YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE;
+ STREAM_START_EVENT_INIT(*event, token->data.stream_start.encoding,
+ token->start_mark, token->start_mark);
+ SKIP_TOKEN(parser);
+
+ return 1;
+}
+
+/*
+ * Parse the productions:
+ * implicit_document ::= block_node DOCUMENT-END*
+ * *
+ * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+ * *************************
+ */
+
+static int
+yaml_parser_parse_document_start(yaml_parser_t *parser, yaml_event_t *event,
+ int implicit)
+{
+ yaml_token_t *token;
+ yaml_titleVersion_directive_t *titleVersion_directive = NULL;
+ struct {
+ yaml_tag_directive_t *start;
+ yaml_tag_directive_t *end;
+ } tag_directives = { NULL, NULL };
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ /* Parse extra document end indicators. */
+
+ if (!implicit)
+ {
+ while (token->type == YAML_DOCUMENT_END_TOKEN) {
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+ }
+ }
+
+ /* Parse an implicit document. */
+
+ if (implicit && token->type != YAML_titleVersion_DIRECTIVE_TOKEN &&
+ token->type != YAML_TAG_DIRECTIVE_TOKEN &&
+ token->type != YAML_DOCUMENT_START_TOKEN &&
+ token->type != YAML_STREAM_END_TOKEN)
+ {
+ if (!yaml_parser_process_directives(parser, NULL, NULL, NULL))
+ return 0;
+ if (!PUSH(parser, parser->states, YAML_PARSE_DOCUMENT_END_STATE))
+ return 0;
+ parser->state = YAML_PARSE_BLOCK_NODE_STATE;
+ DOCUMENT_START_EVENT_INIT(*event, NULL, NULL, NULL, 1,
+ token->start_mark, token->start_mark);
+ return 1;
+ }
+
+ /* Parse an explicit document. */
+
+ else if (token->type != YAML_STREAM_END_TOKEN)
+ {
+ yaml_mark_t start_mark, end_mark;
+ start_mark = token->start_mark;
+ if (!yaml_parser_process_directives(parser, &titleVersion_directive,
+ &tag_directives.start, &tag_directives.end))
+ return 0;
+ token = PEEK_TOKEN(parser);
+ if (!token) goto error;
+ if (token->type != YAML_DOCUMENT_START_TOKEN) {
+ yaml_parser_set_parser_error(parser,
+ "did not find expected ", token->start_mark);
+ goto error;
+ }
+ if (!PUSH(parser, parser->states, YAML_PARSE_DOCUMENT_END_STATE))
+ goto error;
+ parser->state = YAML_PARSE_DOCUMENT_CONTENT_STATE;
+ end_mark = token->end_mark;
+ DOCUMENT_START_EVENT_INIT(*event, titleVersion_directive,
+ tag_directives.start, tag_directives.end, 0,
+ start_mark, end_mark);
+ SKIP_TOKEN(parser);
+ titleVersion_directive = NULL;
+ tag_directives.start = tag_directives.end = NULL;
+ return 1;
+ }
+
+ /* Parse the stream end. */
+
+ else
+ {
+ parser->state = YAML_PARSE_END_STATE;
+ STREAM_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
+ SKIP_TOKEN(parser);
+ return 1;
+ }
+
+error:
+ yaml_free(titleVersion_directive);
+ while (tag_directives.start != tag_directives.end) {
+ yaml_free(tag_directives.end[-1].handle);
+ yaml_free(tag_directives.end[-1].prefix);
+ tag_directives.end --;
+ }
+ yaml_free(tag_directives.start);
+ return 0;
+}
+
+/*
+ * Parse the productions:
+ * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+ * ***********
+ */
+
+static int
+yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event)
+{
+ yaml_token_t *token;
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ if (token->type == YAML_titleVersion_DIRECTIVE_TOKEN ||
+ token->type == YAML_TAG_DIRECTIVE_TOKEN ||
+ token->type == YAML_DOCUMENT_START_TOKEN ||
+ token->type == YAML_DOCUMENT_END_TOKEN ||
+ token->type == YAML_STREAM_END_TOKEN) {
+ parser->state = POP(parser, parser->states);
+ return yaml_parser_process_empty_scalar(parser, event,
+ token->start_mark);
+ }
+ else {
+ return yaml_parser_parse_node(parser, event, 1, 0);
+ }
+}
+
+/*
+ * Parse the productions:
+ * implicit_document ::= block_node DOCUMENT-END*
+ * *************
+ * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+ * *************
+ */
+
+static int
+yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event)
+{
+ yaml_token_t *token;
+ yaml_mark_t start_mark, end_mark;
+ int implicit = 1;
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ start_mark = end_mark = token->start_mark;
+
+ if (token->type == YAML_DOCUMENT_END_TOKEN) {
+ end_mark = token->end_mark;
+ SKIP_TOKEN(parser);
+ implicit = 0;
+ }
+
+ while (!STACK_EMPTY(parser, parser->tag_directives)) {
+ yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
+ yaml_free(tag_directive.handle);
+ yaml_free(tag_directive.prefix);
+ }
+
+ parser->state = YAML_PARSE_DOCUMENT_START_STATE;
+ DOCUMENT_END_EVENT_INIT(*event, implicit, start_mark, end_mark);
+
+ return 1;
+}
+
+/*
+ * Parse the productions:
+ * block_node_or_indentless_sequence ::=
+ * ALIAS
+ * *****
+ * | properties (block_content | indentless_block_sequence)?
+ * ********** *
+ * | block_content | indentless_block_sequence
+ * *
+ * block_node ::= ALIAS
+ * *****
+ * | properties block_content?
+ * ********** *
+ * | block_content
+ * *
+ * flow_node ::= ALIAS
+ * *****
+ * | properties flow_content?
+ * ********** *
+ * | flow_content
+ * *
+ * properties ::= TAG ANCHOR? | ANCHOR TAG?
+ * *************************
+ * block_content ::= block_collection | flow_collection | SCALAR
+ * ******
+ * flow_content ::= flow_collection | SCALAR
+ * ******
+ */
+
+static int
+yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event,
+ int block, int indentless_sequence)
+{
+ yaml_token_t *token;
+ yaml_char_t *anchor = NULL;
+ yaml_char_t *tag_handle = NULL;
+ yaml_char_t *tag_suffix = NULL;
+ yaml_char_t *tag = NULL;
+ yaml_mark_t start_mark, end_mark, tag_mark;
+ int implicit;
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ if (token->type == YAML_ALIAS_TOKEN)
+ {
+ parser->state = POP(parser, parser->states);
+ ALIAS_EVENT_INIT(*event, token->data.alias.value,
+ token->start_mark, token->end_mark);
+ SKIP_TOKEN(parser);
+ return 1;
+ }
+
+ else
+ {
+ start_mark = end_mark = token->start_mark;
+
+ if (token->type == YAML_ANCHOR_TOKEN)
+ {
+ anchor = token->data.anchor.value;
+ start_mark = token->start_mark;
+ end_mark = token->end_mark;
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) goto error;
+ if (token->type == YAML_TAG_TOKEN)
+ {
+ tag_handle = token->data.tag.handle;
+ tag_suffix = token->data.tag.suffix;
+ tag_mark = token->start_mark;
+ end_mark = token->end_mark;
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) goto error;
+ }
+ }
+ else if (token->type == YAML_TAG_TOKEN)
+ {
+ tag_handle = token->data.tag.handle;
+ tag_suffix = token->data.tag.suffix;
+ start_mark = tag_mark = token->start_mark;
+ end_mark = token->end_mark;
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) goto error;
+ if (token->type == YAML_ANCHOR_TOKEN)
+ {
+ anchor = token->data.anchor.value;
+ end_mark = token->end_mark;
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) goto error;
+ }
+ }
+
+ if (tag_handle) {
+ if (!*tag_handle) {
+ tag = tag_suffix;
+ yaml_free(tag_handle);
+ tag_handle = tag_suffix = NULL;
+ }
+ else {
+ yaml_tag_directive_t *tag_directive;
+ for (tag_directive = parser->tag_directives.start;
+ tag_directive != parser->tag_directives.top;
+ tag_directive ++) {
+ if (strcmp((char *)tag_directive->handle, (char *)tag_handle) == 0) {
+ size_t prefix_len = strlen((char *)tag_directive->prefix);
+ size_t suffix_len = strlen((char *)tag_suffix);
+ tag = yaml_malloc(prefix_len+suffix_len+1);
+ if (!tag) {
+ parser->error = YAML_MEMORY_ERROR;
+ goto error;
+ }
+ memcpy(tag, tag_directive->prefix, prefix_len);
+ memcpy(tag+prefix_len, tag_suffix, suffix_len);
+ tag[prefix_len+suffix_len] = '\0';
+ yaml_free(tag_handle);
+ yaml_free(tag_suffix);
+ tag_handle = tag_suffix = NULL;
+ break;
+ }
+ }
+ if (!tag) {
+ yaml_parser_set_parser_error_context(parser,
+ "while parsing a node", start_mark,
+ "found undefined tag handle", tag_mark);
+ goto error;
+ }
+ }
+ }
+
+ implicit = (!tag || !*tag);
+ if (indentless_sequence && token->type == YAML_BLOCK_ENTRY_TOKEN) {
+ end_mark = token->end_mark;
+ parser->state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE;
+ SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
+ YAML_BLOCK_SEQUENCE_STYLE, start_mark, end_mark);
+ return 1;
+ }
+ else {
+ if (token->type == YAML_SCALAR_TOKEN) {
+ int plain_implicit = 0;
+ int quoted_implicit = 0;
+ end_mark = token->end_mark;
+ if ((token->data.scalar.style == YAML_PLAIN_SCALAR_STYLE && !tag)
+ || (tag && strcmp((char *)tag, "!") == 0)) {
+ plain_implicit = 1;
+ }
+ else if (!tag) {
+ quoted_implicit = 1;
+ }
+ parser->state = POP(parser, parser->states);
+ SCALAR_EVENT_INIT(*event, anchor, tag,
+ token->data.scalar.value, token->data.scalar.length,
+ plain_implicit, quoted_implicit,
+ token->data.scalar.style, start_mark, end_mark);
+ SKIP_TOKEN(parser);
+ return 1;
+ }
+ else if (token->type == YAML_FLOW_SEQUENCE_START_TOKEN) {
+ end_mark = token->end_mark;
+ parser->state = YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE;
+ SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
+ YAML_FLOW_SEQUENCE_STYLE, start_mark, end_mark);
+ return 1;
+ }
+ else if (token->type == YAML_FLOW_MAPPING_START_TOKEN) {
+ end_mark = token->end_mark;
+ parser->state = YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE;
+ MAPPING_START_EVENT_INIT(*event, anchor, tag, implicit,
+ YAML_FLOW_MAPPING_STYLE, start_mark, end_mark);
+ return 1;
+ }
+ else if (block && token->type == YAML_BLOCK_SEQUENCE_START_TOKEN) {
+ end_mark = token->end_mark;
+ parser->state = YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE;
+ SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
+ YAML_BLOCK_SEQUENCE_STYLE, start_mark, end_mark);
+ return 1;
+ }
+ else if (block && token->type == YAML_BLOCK_MAPPING_START_TOKEN) {
+ end_mark = token->end_mark;
+ parser->state = YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE;
+ MAPPING_START_EVENT_INIT(*event, anchor, tag, implicit,
+ YAML_BLOCK_MAPPING_STYLE, start_mark, end_mark);
+ return 1;
+ }
+ else if (anchor || tag) {
+ yaml_char_t *value = yaml_malloc(1);
+ if (!value) {
+ parser->error = YAML_MEMORY_ERROR;
+ goto error;
+ }
+ value[0] = '\0';
+ parser->state = POP(parser, parser->states);
+ SCALAR_EVENT_INIT(*event, anchor, tag, value, 0,
+ implicit, 0, YAML_PLAIN_SCALAR_STYLE,
+ start_mark, end_mark);
+ return 1;
+ }
+ else {
+ yaml_parser_set_parser_error_context(parser,
+ (block ? "while parsing a block node"
+ : "while parsing a flow node"), start_mark,
+ "did not find expected node content", token->start_mark);
+ goto error;
+ }
+ }
+ }
+
+error:
+ yaml_free(anchor);
+ yaml_free(tag_handle);
+ yaml_free(tag_suffix);
+ yaml_free(tag);
+
+ return 0;
+}
+
+/*
+ * Parse the productions:
+ * block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+ * ******************** *********** * *********
+ */
+
+static int
+yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser,
+ yaml_event_t *event, int first)
+{
+ yaml_token_t *token;
+
+ if (first) {
+ token = PEEK_TOKEN(parser);
+ if (!PUSH(parser, parser->marks, token->start_mark))
+ return 0;
+ SKIP_TOKEN(parser);
+ }
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ if (token->type == YAML_BLOCK_ENTRY_TOKEN)
+ {
+ yaml_mark_t mark = token->end_mark;
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+ if (token->type != YAML_BLOCK_ENTRY_TOKEN &&
+ token->type != YAML_BLOCK_END_TOKEN) {
+ if (!PUSH(parser, parser->states,
+ YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE))
+ return 0;
+ return yaml_parser_parse_node(parser, event, 1, 0);
+ }
+ else {
+ parser->state = YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE;
+ return yaml_parser_process_empty_scalar(parser, event, mark);
+ }
+ }
+
+ else if (token->type == YAML_BLOCK_END_TOKEN)
+ {
+ yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */
+ parser->state = POP(parser, parser->states);
+ dummy_mark = POP(parser, parser->marks);
+ SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
+ SKIP_TOKEN(parser);
+ return 1;
+ }
+
+ else
+ {
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a block collection", POP(parser, parser->marks),
+ "did not find expected '-' indicator", token->start_mark);
+ }
+}
+
+/*
+ * Parse the productions:
+ * indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+ * *********** *
+ */
+
+static int
+yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser,
+ yaml_event_t *event)
+{
+ yaml_token_t *token;
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ if (token->type == YAML_BLOCK_ENTRY_TOKEN)
+ {
+ yaml_mark_t mark = token->end_mark;
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+ if (token->type != YAML_BLOCK_ENTRY_TOKEN &&
+ token->type != YAML_KEY_TOKEN &&
+ token->type != YAML_VALUE_TOKEN &&
+ token->type != YAML_BLOCK_END_TOKEN) {
+ if (!PUSH(parser, parser->states,
+ YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE))
+ return 0;
+ return yaml_parser_parse_node(parser, event, 1, 0);
+ }
+ else {
+ parser->state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE;
+ return yaml_parser_process_empty_scalar(parser, event, mark);
+ }
+ }
+
+ else
+ {
+ parser->state = POP(parser, parser->states);
+ SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->start_mark);
+ return 1;
+ }
+}
+
+/*
+ * Parse the productions:
+ * block_mapping ::= BLOCK-MAPPING_START
+ * *******************
+ * ((KEY block_node_or_indentless_sequence?)?
+ * *** *
+ * (VALUE block_node_or_indentless_sequence?)?)*
+ *
+ * BLOCK-END
+ * *********
+ */
+
+static int
+yaml_parser_parse_block_mapping_key(yaml_parser_t *parser,
+ yaml_event_t *event, int first)
+{
+ yaml_token_t *token;
+
+ if (first) {
+ token = PEEK_TOKEN(parser);
+ if (!PUSH(parser, parser->marks, token->start_mark))
+ return 0;
+ SKIP_TOKEN(parser);
+ }
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ if (token->type == YAML_KEY_TOKEN)
+ {
+ yaml_mark_t mark = token->end_mark;
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+ if (token->type != YAML_KEY_TOKEN &&
+ token->type != YAML_VALUE_TOKEN &&
+ token->type != YAML_BLOCK_END_TOKEN) {
+ if (!PUSH(parser, parser->states,
+ YAML_PARSE_BLOCK_MAPPING_VALUE_STATE))
+ return 0;
+ return yaml_parser_parse_node(parser, event, 1, 1);
+ }
+ else {
+ parser->state = YAML_PARSE_BLOCK_MAPPING_VALUE_STATE;
+ return yaml_parser_process_empty_scalar(parser, event, mark);
+ }
+ }
+
+ else if (token->type == YAML_BLOCK_END_TOKEN)
+ {
+ yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */
+ parser->state = POP(parser, parser->states);
+ dummy_mark = POP(parser, parser->marks);
+ MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
+ SKIP_TOKEN(parser);
+ return 1;
+ }
+
+ else
+ {
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a block mapping", POP(parser, parser->marks),
+ "did not find expected key", token->start_mark);
+ }
+}
+
+/*
+ * Parse the productions:
+ * block_mapping ::= BLOCK-MAPPING_START
+ *
+ * ((KEY block_node_or_indentless_sequence?)?
+ *
+ * (VALUE block_node_or_indentless_sequence?)?)*
+ * ***** *
+ * BLOCK-END
+ *
+ */
+
+static int
+yaml_parser_parse_block_mapping_value(yaml_parser_t *parser,
+ yaml_event_t *event)
+{
+ yaml_token_t *token;
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ if (token->type == YAML_VALUE_TOKEN)
+ {
+ yaml_mark_t mark = token->end_mark;
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+ if (token->type != YAML_KEY_TOKEN &&
+ token->type != YAML_VALUE_TOKEN &&
+ token->type != YAML_BLOCK_END_TOKEN) {
+ if (!PUSH(parser, parser->states,
+ YAML_PARSE_BLOCK_MAPPING_KEY_STATE))
+ return 0;
+ return yaml_parser_parse_node(parser, event, 1, 1);
+ }
+ else {
+ parser->state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE;
+ return yaml_parser_process_empty_scalar(parser, event, mark);
+ }
+ }
+
+ else
+ {
+ parser->state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE;
+ return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
+ }
+}
+
+/*
+ * Parse the productions:
+ * flow_sequence ::= FLOW-SEQUENCE-START
+ * *******************
+ * (flow_sequence_entry FLOW-ENTRY)*
+ * * **********
+ * flow_sequence_entry?
+ * *
+ * FLOW-SEQUENCE-END
+ * *****************
+ * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+ * *
+ */
+
+static int
+yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser,
+ yaml_event_t *event, int first)
+{
+ yaml_token_t *token;
+ yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */
+
+ if (first) {
+ token = PEEK_TOKEN(parser);
+ if (!PUSH(parser, parser->marks, token->start_mark))
+ return 0;
+ SKIP_TOKEN(parser);
+ }
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ if (token->type != YAML_FLOW_SEQUENCE_END_TOKEN)
+ {
+ if (!first) {
+ if (token->type == YAML_FLOW_ENTRY_TOKEN) {
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+ }
+ else {
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a flow sequence", POP(parser, parser->marks),
+ "did not find expected ',' or ']'", token->start_mark);
+ }
+ }
+
+ if (token->type == YAML_KEY_TOKEN) {
+ parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE;
+ MAPPING_START_EVENT_INIT(*event, NULL, NULL,
+ 1, YAML_FLOW_MAPPING_STYLE,
+ token->start_mark, token->end_mark);
+ SKIP_TOKEN(parser);
+ return 1;
+ }
+
+ else if (token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
+ if (!PUSH(parser, parser->states,
+ YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE))
+ return 0;
+ return yaml_parser_parse_node(parser, event, 0, 0);
+ }
+ }
+
+ parser->state = POP(parser, parser->states);
+ dummy_mark = POP(parser, parser->marks);
+ SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
+ SKIP_TOKEN(parser);
+ return 1;
+}
+
+/*
+ * Parse the productions:
+ * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+ * *** *
+ */
+
+static int
+yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser,
+ yaml_event_t *event)
+{
+ yaml_token_t *token;
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ if (token->type != YAML_VALUE_TOKEN && token->type != YAML_FLOW_ENTRY_TOKEN
+ && token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
+ if (!PUSH(parser, parser->states,
+ YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE))
+ return 0;
+ return yaml_parser_parse_node(parser, event, 0, 0);
+ }
+ else {
+ yaml_mark_t mark = token->end_mark;
+ SKIP_TOKEN(parser);
+ parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE;
+ return yaml_parser_process_empty_scalar(parser, event, mark);
+ }
+}
+
+/*
+ * Parse the productions:
+ * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+ * ***** *
+ */
+
+static int
+yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser,
+ yaml_event_t *event)
+{
+ yaml_token_t *token;
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ if (token->type == YAML_VALUE_TOKEN) {
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+ if (token->type != YAML_FLOW_ENTRY_TOKEN
+ && token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
+ if (!PUSH(parser, parser->states,
+ YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE))
+ return 0;
+ return yaml_parser_parse_node(parser, event, 0, 0);
+ }
+ }
+ parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE;
+ return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
+}
+
+/*
+ * Parse the productions:
+ * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+ * *
+ */
+
+static int
+yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser,
+ yaml_event_t *event)
+{
+ yaml_token_t *token;
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE;
+
+ MAPPING_END_EVENT_INIT(*event, token->start_mark, token->start_mark);
+ return 1;
+}
+
+/*
+ * Parse the productions:
+ * flow_mapping ::= FLOW-MAPPING-START
+ * ******************
+ * (flow_mapping_entry FLOW-ENTRY)*
+ * * **********
+ * flow_mapping_entry?
+ * ******************
+ * FLOW-MAPPING-END
+ * ****************
+ * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+ * * *** *
+ */
+
+static int
+yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser,
+ yaml_event_t *event, int first)
+{
+ yaml_token_t *token;
+ yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */
+
+ if (first) {
+ token = PEEK_TOKEN(parser);
+ if (!PUSH(parser, parser->marks, token->start_mark))
+ return 0;
+ SKIP_TOKEN(parser);
+ }
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ if (token->type != YAML_FLOW_MAPPING_END_TOKEN)
+ {
+ if (!first) {
+ if (token->type == YAML_FLOW_ENTRY_TOKEN) {
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+ }
+ else {
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a flow mapping", POP(parser, parser->marks),
+ "did not find expected ',' or '}'", token->start_mark);
+ }
+ }
+
+ if (token->type == YAML_KEY_TOKEN) {
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+ if (token->type != YAML_VALUE_TOKEN
+ && token->type != YAML_FLOW_ENTRY_TOKEN
+ && token->type != YAML_FLOW_MAPPING_END_TOKEN) {
+ if (!PUSH(parser, parser->states,
+ YAML_PARSE_FLOW_MAPPING_VALUE_STATE))
+ return 0;
+ return yaml_parser_parse_node(parser, event, 0, 0);
+ }
+ else {
+ parser->state = YAML_PARSE_FLOW_MAPPING_VALUE_STATE;
+ return yaml_parser_process_empty_scalar(parser, event,
+ token->start_mark);
+ }
+ }
+ else if (token->type != YAML_FLOW_MAPPING_END_TOKEN) {
+ if (!PUSH(parser, parser->states,
+ YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE))
+ return 0;
+ return yaml_parser_parse_node(parser, event, 0, 0);
+ }
+ }
+
+ parser->state = POP(parser, parser->states);
+ dummy_mark = POP(parser, parser->marks);
+ MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
+ SKIP_TOKEN(parser);
+ return 1;
+}
+
+/*
+ * Parse the productions:
+ * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+ * * ***** *
+ */
+
+static int
+yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser,
+ yaml_event_t *event, int empty)
+{
+ yaml_token_t *token;
+
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+
+ if (empty) {
+ parser->state = YAML_PARSE_FLOW_MAPPING_KEY_STATE;
+ return yaml_parser_process_empty_scalar(parser, event,
+ token->start_mark);
+ }
+
+ if (token->type == YAML_VALUE_TOKEN) {
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) return 0;
+ if (token->type != YAML_FLOW_ENTRY_TOKEN
+ && token->type != YAML_FLOW_MAPPING_END_TOKEN) {
+ if (!PUSH(parser, parser->states,
+ YAML_PARSE_FLOW_MAPPING_KEY_STATE))
+ return 0;
+ return yaml_parser_parse_node(parser, event, 0, 0);
+ }
+ }
+
+ parser->state = YAML_PARSE_FLOW_MAPPING_KEY_STATE;
+ return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
+}
+
+/*
+ * Generate an empty scalar event.
+ */
+
+static int
+yaml_parser_process_empty_scalar(yaml_parser_t *parser, yaml_event_t *event,
+ yaml_mark_t mark)
+{
+ yaml_char_t *value;
+
+ value = yaml_malloc(1);
+ if (!value) {
+ parser->error = YAML_MEMORY_ERROR;
+ return 0;
+ }
+ value[0] = '\0';
+
+ SCALAR_EVENT_INIT(*event, NULL, NULL, value, 0,
+ 1, 0, YAML_PLAIN_SCALAR_STYLE, mark, mark);
+
+ return 1;
+}
+
+/*
+ * Parse directives.
+ */
+
+static int
+yaml_parser_process_directives(yaml_parser_t *parser,
+ yaml_titleVersion_directive_t **titleVersion_directive_ref,
+ yaml_tag_directive_t **tag_directives_start_ref,
+ yaml_tag_directive_t **tag_directives_end_ref)
+{
+ yaml_tag_directive_t default_tag_directives[] = {
+ {(yaml_char_t *)"!", (yaml_char_t *)"!"},
+ {(yaml_char_t *)"!!", (yaml_char_t *)"tag:yaml.org,2002:"},
+ {NULL, NULL}
+ };
+ yaml_tag_directive_t *default_tag_directive;
+ yaml_titleVersion_directive_t *titleVersion_directive = NULL;
+ struct {
+ yaml_tag_directive_t *start;
+ yaml_tag_directive_t *end;
+ yaml_tag_directive_t *top;
+ } tag_directives = { NULL, NULL, NULL };
+ yaml_token_t *token;
+
+ if (!STACK_INIT(parser, tag_directives, INITIAL_STACK_SIZE))
+ goto error;
+
+ token = PEEK_TOKEN(parser);
+ if (!token) goto error;
+
+ while (token->type == YAML_titleVersion_DIRECTIVE_TOKEN ||
+ token->type == YAML_TAG_DIRECTIVE_TOKEN)
+ {
+ if (token->type == YAML_titleVersion_DIRECTIVE_TOKEN) {
+ if (titleVersion_directive) {
+ yaml_parser_set_parser_error(parser,
+ "found duplicate %YAML directive", token->start_mark);
+ goto error;
+ }
+ if (token->data.titleVersion_directive.major != 1
+ || token->data.titleVersion_directive.minor != 1) {
+ yaml_parser_set_parser_error(parser,
+ "found incompatible YAML document", token->start_mark);
+ goto error;
+ }
+ titleVersion_directive = yaml_malloc(sizeof(yaml_titleVersion_directive_t));
+ if (!titleVersion_directive) {
+ parser->error = YAML_MEMORY_ERROR;
+ goto error;
+ }
+ titleVersion_directive->major = token->data.titleVersion_directive.major;
+ titleVersion_directive->minor = token->data.titleVersion_directive.minor;
+ }
+
+ else if (token->type == YAML_TAG_DIRECTIVE_TOKEN) {
+ yaml_tag_directive_t value;
+ value.handle = token->data.tag_directive.handle;
+ value.prefix = token->data.tag_directive.prefix;
+
+ if (!yaml_parser_append_tag_directive(parser, value, 0,
+ token->start_mark))
+ goto error;
+ if (!PUSH(parser, tag_directives, value))
+ goto error;
+ }
+
+ SKIP_TOKEN(parser);
+ token = PEEK_TOKEN(parser);
+ if (!token) goto error;
+ }
+
+ for (default_tag_directive = default_tag_directives;
+ default_tag_directive->handle; default_tag_directive++) {
+ if (!yaml_parser_append_tag_directive(parser, *default_tag_directive, 1,
+ token->start_mark))
+ goto error;
+ }
+
+ if (titleVersion_directive_ref) {
+ *titleVersion_directive_ref = titleVersion_directive;
+ }
+ if (tag_directives_start_ref) {
+ if (STACK_EMPTY(parser, tag_directives)) {
+ *tag_directives_start_ref = *tag_directives_end_ref = NULL;
+ STACK_DEL(parser, tag_directives);
+ }
+ else {
+ *tag_directives_start_ref = tag_directives.start;
+ *tag_directives_end_ref = tag_directives.top;
+ }
+ }
+ else {
+ STACK_DEL(parser, tag_directives);
+ }
+
+ return 1;
+
+error:
+ yaml_free(titleVersion_directive);
+ while (!STACK_EMPTY(parser, tag_directives)) {
+ yaml_tag_directive_t tag_directive = POP(parser, tag_directives);
+ yaml_free(tag_directive.handle);
+ yaml_free(tag_directive.prefix);
+ }
+ STACK_DEL(parser, tag_directives);
+ return 0;
+}
+
+/*
+ * Append a tag directive to the directives stack.
+ */
+
+static int
+yaml_parser_append_tag_directive(yaml_parser_t *parser,
+ yaml_tag_directive_t value, int allow_duplicates, yaml_mark_t mark)
+{
+ yaml_tag_directive_t *tag_directive;
+ yaml_tag_directive_t copy = { NULL, NULL };
+
+ for (tag_directive = parser->tag_directives.start;
+ tag_directive != parser->tag_directives.top; tag_directive ++) {
+ if (strcmp((char *)value.handle, (char *)tag_directive->handle) == 0) {
+ if (allow_duplicates)
+ return 1;
+ return yaml_parser_set_parser_error(parser,
+ "found duplicate %TAG directive", mark);
+ }
+ }
+
+ copy.handle = yaml_strdup(value.handle);
+ copy.prefix = yaml_strdup(value.prefix);
+ if (!copy.handle || !copy.prefix) {
+ parser->error = YAML_MEMORY_ERROR;
+ goto error;
+ }
+
+ if (!PUSH(parser, parser->tag_directives, copy))
+ goto error;
+
+ return 1;
+
+error:
+ yaml_free(copy.handle);
+ yaml_free(copy.prefix);
+ return 0;
+}
+
diff --git a/libyaml/reader.c b/libyaml/reader.c
new file mode 100644
index 0000000..e7ab27a
--- /dev/null
+++ b/libyaml/reader.c
@@ -0,0 +1,465 @@
+
+#include "libyaml/yaml_private.h"
+
+/*
+ * Declarations.
+ */
+
+static int
+yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem,
+ size_t offset, int value);
+
+static int
+yaml_parser_update_raw_buffer(yaml_parser_t *parser);
+
+static int
+yaml_parser_determine_encoding(yaml_parser_t *parser);
+
+YAML_DECLARE(int)
+yaml_parser_update_buffer(yaml_parser_t *parser, size_t length);
+
+/*
+ * Set the reader error and return 0.
+ */
+
+static int
+yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem,
+ size_t offset, int value)
+{
+ parser->error = YAML_READER_ERROR;
+ parser->problem = problem;
+ parser->problem_offset = offset;
+ parser->problem_value = value;
+
+ return 0;
+}
+
+/*
+ * Byte order marks.
+ */
+
+#define BOM_UTF8 "\xef\xbb\xbf"
+#define BOM_UTF16LE "\xff\xfe"
+#define BOM_UTF16BE "\xfe\xff"
+
+/*
+ * Determine the input stream encoding by checking the BOM symbol. If no BOM is
+ * found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
+ */
+
+static int
+yaml_parser_determine_encoding(yaml_parser_t *parser)
+{
+ /* Ensure that we had enough bytes in the raw buffer. */
+
+ while (!parser->eof
+ && parser->raw_buffer.last - parser->raw_buffer.pointer < 3) {
+ if (!yaml_parser_update_raw_buffer(parser)) {
+ return 0;
+ }
+ }
+
+ /* Determine the encoding. */
+
+ if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 2
+ && !memcmp(parser->raw_buffer.pointer, BOM_UTF16LE, 2)) {
+ parser->encoding = YAML_UTF16LE_ENCODING;
+ parser->raw_buffer.pointer += 2;
+ parser->offset += 2;
+ }
+ else if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 2
+ && !memcmp(parser->raw_buffer.pointer, BOM_UTF16BE, 2)) {
+ parser->encoding = YAML_UTF16BE_ENCODING;
+ parser->raw_buffer.pointer += 2;
+ parser->offset += 2;
+ }
+ else if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 3
+ && !memcmp(parser->raw_buffer.pointer, BOM_UTF8, 3)) {
+ parser->encoding = YAML_UTF8_ENCODING;
+ parser->raw_buffer.pointer += 3;
+ parser->offset += 3;
+ }
+ else {
+ parser->encoding = YAML_UTF8_ENCODING;
+ }
+
+ return 1;
+}
+
+/*
+ * Update the raw buffer.
+ */
+
+static int
+yaml_parser_update_raw_buffer(yaml_parser_t *parser)
+{
+ size_t size_read = 0;
+
+ /* Return if the raw buffer is full. */
+
+ if (parser->raw_buffer.start == parser->raw_buffer.pointer
+ && parser->raw_buffer.last == parser->raw_buffer.end)
+ return 1;
+
+ /* Return on EOF. */
+
+ if (parser->eof) return 1;
+
+ /* Move the remaining bytes in the raw buffer to the beginning. */
+
+ if (parser->raw_buffer.start < parser->raw_buffer.pointer
+ && parser->raw_buffer.pointer < parser->raw_buffer.last) {
+ memmove(parser->raw_buffer.start, parser->raw_buffer.pointer,
+ parser->raw_buffer.last - parser->raw_buffer.pointer);
+ }
+ parser->raw_buffer.last -=
+ parser->raw_buffer.pointer - parser->raw_buffer.start;
+ parser->raw_buffer.pointer = parser->raw_buffer.start;
+
+ /* Call the read handler to fill the buffer. */
+
+ if (!parser->read_handler(parser->read_handler_data, parser->raw_buffer.last,
+ parser->raw_buffer.end - parser->raw_buffer.last, &size_read)) {
+ return yaml_parser_set_reader_error(parser, "input error",
+ parser->offset, -1);
+ }
+ parser->raw_buffer.last += size_read;
+ if (!size_read) {
+ parser->eof = 1;
+ }
+
+ return 1;
+}
+
+/*
+ * Ensure that the buffer contains at least `length` characters.
+ * Return 1 on success, 0 on failure.
+ *
+ * The length is supposed to be significantly less that the buffer size.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_update_buffer(yaml_parser_t *parser, size_t length)
+{
+ int first = 1;
+
+ assert(parser->read_handler); /* Read handler must be set. */
+
+ /* If the EOF flag is set and the raw buffer is empty, do nothing. */
+
+ if (parser->eof && parser->raw_buffer.pointer == parser->raw_buffer.last)
+ return 1;
+
+ /* Return if the buffer contains enough characters. */
+
+ if (parser->unread >= length)
+ return 1;
+
+ /* Determine the input encoding if it is not known yet. */
+
+ if (!parser->encoding) {
+ if (!yaml_parser_determine_encoding(parser))
+ return 0;
+ }
+
+ /* Move the unread characters to the beginning of the buffer. */
+
+ if (parser->buffer.start < parser->buffer.pointer
+ && parser->buffer.pointer < parser->buffer.last) {
+ size_t size = parser->buffer.last - parser->buffer.pointer;
+ memmove(parser->buffer.start, parser->buffer.pointer, size);
+ parser->buffer.pointer = parser->buffer.start;
+ parser->buffer.last = parser->buffer.start + size;
+ }
+ else if (parser->buffer.pointer == parser->buffer.last) {
+ parser->buffer.pointer = parser->buffer.start;
+ parser->buffer.last = parser->buffer.start;
+ }
+
+ /* Fill the buffer until it has enough characters. */
+
+ while (parser->unread < length)
+ {
+ /* Fill the raw buffer if necessary. */
+
+ if (!first || parser->raw_buffer.pointer == parser->raw_buffer.last) {
+ if (!yaml_parser_update_raw_buffer(parser)) return 0;
+ }
+ first = 0;
+
+ /* Decode the raw buffer. */
+
+ while (parser->raw_buffer.pointer != parser->raw_buffer.last)
+ {
+ unsigned int value = 0, value2 = 0;
+ int incomplete = 0;
+ unsigned char octet;
+ unsigned int width = 0;
+ int low, high;
+ size_t k;
+ size_t raw_unread = parser->raw_buffer.last - parser->raw_buffer.pointer;
+
+ /* Decode the next character. */
+
+ switch (parser->encoding)
+ {
+ case YAML_UTF8_ENCODING:
+
+ /*
+ * Decode a UTF-8 character. Check RFC 3629
+ * (http://www.ietf.org/rfc/rfc3629.txt) for more details.
+ *
+ * The following table (taken from the RFC) is used for
+ * decoding.
+ *
+ * Char. number range | UTF-8 octet sequence
+ * (hexadecimal) | (binary)
+ * --------------------+------------------------------------
+ * 0000 0000-0000 007F | 0xxxxxxx
+ * 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
+ * 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
+ * 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ *
+ * Additionally, the characters in the range 0xD800-0xDFFF
+ * are prohibited as they are reserved for use with UTF-16
+ * surrogate pairs.
+ */
+
+ /* Determine the length of the UTF-8 sequence. */
+
+ octet = parser->raw_buffer.pointer[0];
+ width = (octet & 0x80) == 0x00 ? 1 :
+ (octet & 0xE0) == 0xC0 ? 2 :
+ (octet & 0xF0) == 0xE0 ? 3 :
+ (octet & 0xF8) == 0xF0 ? 4 : 0;
+
+ /* Check if the leading octet is valid. */
+
+ if (!width)
+ return yaml_parser_set_reader_error(parser,
+ "invalid leading UTF-8 octet",
+ parser->offset, octet);
+
+ /* Check if the raw buffer contains an incomplete character. */
+
+ if (width > raw_unread) {
+ if (parser->eof) {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-8 octet sequence",
+ parser->offset, -1);
+ }
+ incomplete = 1;
+ break;
+ }
+
+ /* Decode the leading octet. */
+
+ value = (octet & 0x80) == 0x00 ? octet & 0x7F :
+ (octet & 0xE0) == 0xC0 ? octet & 0x1F :
+ (octet & 0xF0) == 0xE0 ? octet & 0x0F :
+ (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
+
+ /* Check and decode the trailing octets. */
+
+ for (k = 1; k < width; k ++)
+ {
+ octet = parser->raw_buffer.pointer[k];
+
+ /* Check if the octet is valid. */
+
+ if ((octet & 0xC0) != 0x80)
+ return yaml_parser_set_reader_error(parser,
+ "invalid trailing UTF-8 octet",
+ parser->offset+k, octet);
+
+ /* Decode the octet. */
+
+ value = (value << 6) + (octet & 0x3F);
+ }
+
+ /* Check the length of the sequence against the value. */
+
+ if (!((width == 1) ||
+ (width == 2 && value >= 0x80) ||
+ (width == 3 && value >= 0x800) ||
+ (width == 4 && value >= 0x10000)))
+ return yaml_parser_set_reader_error(parser,
+ "invalid length of a UTF-8 sequence",
+ parser->offset, -1);
+
+ /* Check the range of the value. */
+
+ if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF)
+ return yaml_parser_set_reader_error(parser,
+ "invalid Unicode character",
+ parser->offset, value);
+
+ break;
+
+ case YAML_UTF16LE_ENCODING:
+ case YAML_UTF16BE_ENCODING:
+
+ low = (parser->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
+ high = (parser->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
+
+ /*
+ * The UTF-16 encoding is not as simple as one might
+ * naively think. Check RFC 2781
+ * (http://www.ietf.org/rfc/rfc2781.txt).
+ *
+ * Normally, two subsequent bytes describe a Unicode
+ * character. However a special technique (called a
+ * surrogate pair) is used for specifying character
+ * values larger than 0xFFFF.
+ *
+ * A surrogate pair consists of two pseudo-characters:
+ * high surrogate area (0xD800-0xDBFF)
+ * low surrogate area (0xDC00-0xDFFF)
+ *
+ * The following formulas are used for decoding
+ * and encoding characters using surrogate pairs:
+ *
+ * U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
+ * U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
+ * W1 = 110110yyyyyyyyyy
+ * W2 = 110111xxxxxxxxxx
+ *
+ * where U is the character value, W1 is the high surrogate
+ * area, W2 is the low surrogate area.
+ */
+
+ /* Check for incomplete UTF-16 character. */
+
+ if (raw_unread < 2) {
+ if (parser->eof) {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-16 character",
+ parser->offset, -1);
+ }
+ incomplete = 1;
+ break;
+ }
+
+ /* Get the character. */
+
+ value = parser->raw_buffer.pointer[low]
+ + (parser->raw_buffer.pointer[high] << 8);
+
+ /* Check for unexpected low surrogate area. */
+
+ if ((value & 0xFC00) == 0xDC00)
+ return yaml_parser_set_reader_error(parser,
+ "unexpected low surrogate area",
+ parser->offset, value);
+
+ /* Check for a high surrogate area. */
+
+ if ((value & 0xFC00) == 0xD800) {
+
+ width = 4;
+
+ /* Check for incomplete surrogate pair. */
+
+ if (raw_unread < 4) {
+ if (parser->eof) {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-16 surrogate pair",
+ parser->offset, -1);
+ }
+ incomplete = 1;
+ break;
+ }
+
+ /* Get the next character. */
+
+ value2 = parser->raw_buffer.pointer[low+2]
+ + (parser->raw_buffer.pointer[high+2] << 8);
+
+ /* Check for a low surrogate area. */
+
+ if ((value2 & 0xFC00) != 0xDC00)
+ return yaml_parser_set_reader_error(parser,
+ "expected low surrogate area",
+ parser->offset+2, value2);
+
+ /* Generate the value of the surrogate pair. */
+
+ value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF);
+ }
+
+ else {
+ width = 2;
+ }
+
+ break;
+
+ default:
+ assert(1); /* Impossible. */
+ }
+
+ /* Check if the raw buffer contains enough bytes to form a character. */
+
+ if (incomplete) break;
+
+ /*
+ * Check if the character is in the allowed range:
+ * #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
+ * | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
+ * | [#x10000-#x10FFFF] (32 bit)
+ */
+
+ if (! (value == 0x09 || value == 0x0A || value == 0x0D
+ || (value >= 0x20 && value <= 0x7E)
+ || (value == 0x85) || (value >= 0xA0 && value <= 0xD7FF)
+ || (value >= 0xE000 && value <= 0xFFFD)
+ || (value >= 0x10000 && value <= 0x10FFFF)))
+ return yaml_parser_set_reader_error(parser,
+ "control characters are not allowed",
+ parser->offset, value);
+
+ /* Move the raw pointers. */
+
+ parser->raw_buffer.pointer += width;
+ parser->offset += width;
+
+ /* Finally put the character into the buffer. */
+
+ /* 0000 0000-0000 007F -> 0xxxxxxx */
+ if (value <= 0x7F) {
+ *(parser->buffer.last++) = value;
+ }
+ /* 0000 0080-0000 07FF -> 110xxxxx 10xxxxxx */
+ else if (value <= 0x7FF) {
+ *(parser->buffer.last++) = 0xC0 + (value >> 6);
+ *(parser->buffer.last++) = 0x80 + (value & 0x3F);
+ }
+ /* 0000 0800-0000 FFFF -> 1110xxxx 10xxxxxx 10xxxxxx */
+ else if (value <= 0xFFFF) {
+ *(parser->buffer.last++) = 0xE0 + (value >> 12);
+ *(parser->buffer.last++) = 0x80 + ((value >> 6) & 0x3F);
+ *(parser->buffer.last++) = 0x80 + (value & 0x3F);
+ }
+ /* 0001 0000-0010 FFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ else {
+ *(parser->buffer.last++) = 0xF0 + (value >> 18);
+ *(parser->buffer.last++) = 0x80 + ((value >> 12) & 0x3F);
+ *(parser->buffer.last++) = 0x80 + ((value >> 6) & 0x3F);
+ *(parser->buffer.last++) = 0x80 + (value & 0x3F);
+ }
+
+ parser->unread ++;
+ }
+
+ /* On EOF, put NUL into the buffer and return. */
+
+ if (parser->eof) {
+ *(parser->buffer.last++) = '\0';
+ parser->unread ++;
+ return 1;
+ }
+
+ }
+
+ return 1;
+}
+
diff --git a/libyaml/scanner.c b/libyaml/scanner.c
new file mode 100644
index 0000000..0ed7c7b
--- /dev/null
+++ b/libyaml/scanner.c
@@ -0,0 +1,3570 @@
+
+/*
+ * Introduction
+ * ************
+ *
+ * The following notes assume that you are familiar with the YAML specification
+ * (http://yaml.org/spec/cvs/current.html). We mostly follow it, although in
+ * some cases we are less restrictive that it requires.
+ *
+ * The process of transforming a YAML stream into a sequence of events is
+ * divided on two steps: Scanning and Parsing.
+ *
+ * The Scanner transforms the input stream into a sequence of tokens, while the
+ * parser transform the sequence of tokens produced by the Scanner into a
+ * sequence of parsing events.
+ *
+ * The Scanner is rather clever and complicated. The Parser, on the contrary,
+ * is a straightforward implementation of a recursive-descendant parser (or,
+ * LL(1) parser, as it is usually called).
+ *
+ * Actually there are two issues of Scanning that might be called "clever", the
+ * rest is quite straightforward. The issues are "block collection start" and
+ * "simple keys". Both issues are explained below in details.
+ *
+ * Here the Scanning step is explained and implemented. We start with the list
+ * of all the tokens produced by the Scanner together with short descriptions.
+ *
+ * Now, tokens:
+ *
+ * STREAM-START(encoding) # The stream start.
+ * STREAM-END # The stream end.
+ * titleVersion-DIRECTIVE(major,minor) # The '%YAML' directive.
+ * TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive.
+ * DOCUMENT-START # '---'
+ * DOCUMENT-END # '...'
+ * BLOCK-SEQUENCE-START # Indentation increase denoting a block
+ * BLOCK-MAPPING-START # sequence or a block mapping.
+ * BLOCK-END # Indentation decrease.
+ * FLOW-SEQUENCE-START # '['
+ * FLOW-SEQUENCE-END # ']'
+ * BLOCK-SEQUENCE-START # '{'
+ * BLOCK-SEQUENCE-END # '}'
+ * BLOCK-ENTRY # '-'
+ * FLOW-ENTRY # ','
+ * KEY # '?' or nothing (simple keys).
+ * VALUE # ':'
+ * ALIAS(anchor) # '*anchor'
+ * ANCHOR(anchor) # '&anchor'
+ * TAG(handle,suffix) # '!handle!suffix'
+ * SCALAR(value,style) # A scalar.
+ *
+ * The following two tokens are "virtual" tokens denoting the beginning and the
+ * end of the stream:
+ *
+ * STREAM-START(encoding)
+ * STREAM-END
+ *
+ * We pass the information about the input stream encoding with the
+ * STREAM-START token.
+ *
+ * The next two tokens are responsible for tags:
+ *
+ * titleVersion-DIRECTIVE(major,minor)
+ * TAG-DIRECTIVE(handle,prefix)
+ *
+ * Example:
+ *
+ * %YAML 1.1
+ * %TAG ! !foo
+ * %TAG !yaml! tag:yaml.org,2002:
+ * ---
+ *
+ * The correspoding sequence of tokens:
+ *
+ * STREAM-START(utf-8)
+ * titleVersion-DIRECTIVE(1,1)
+ * TAG-DIRECTIVE("!","!foo")
+ * TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
+ * DOCUMENT-START
+ * STREAM-END
+ *
+ * Note that the titleVersion-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
+ * line.
+ *
+ * The document start and end indicators are represented by:
+ *
+ * DOCUMENT-START
+ * DOCUMENT-END
+ *
+ * Note that if a YAML stream contains an implicit document (without '---'
+ * and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
+ * produced.
+ *
+ * In the following examples, we present whole documents together with the
+ * produced tokens.
+ *
+ * 1. An implicit document:
+ *
+ * 'a scalar'
+ *
+ * Tokens:
+ *
+ * STREAM-START(utf-8)
+ * SCALAR("a scalar",single-quoted)
+ * STREAM-END
+ *
+ * 2. An explicit document:
+ *
+ * ---
+ * 'a scalar'
+ * ...
+ *
+ * Tokens:
+ *
+ * STREAM-START(utf-8)
+ * DOCUMENT-START
+ * SCALAR("a scalar",single-quoted)
+ * DOCUMENT-END
+ * STREAM-END
+ *
+ * 3. Several documents in a stream:
+ *
+ * 'a scalar'
+ * ---
+ * 'another scalar'
+ * ---
+ * 'yet another scalar'
+ *
+ * Tokens:
+ *
+ * STREAM-START(utf-8)
+ * SCALAR("a scalar",single-quoted)
+ * DOCUMENT-START
+ * SCALAR("another scalar",single-quoted)
+ * DOCUMENT-START
+ * SCALAR("yet another scalar",single-quoted)
+ * STREAM-END
+ *
+ * We have already introduced the SCALAR token above. The following tokens are
+ * used to describe aliases, anchors, tag, and scalars:
+ *
+ * ALIAS(anchor)
+ * ANCHOR(anchor)
+ * TAG(handle,suffix)
+ * SCALAR(value,style)
+ *
+ * The following series of examples illustrate the usage of these tokens:
+ *
+ * 1. A recursive sequence:
+ *
+ * &A [ *A ]
+ *
+ * Tokens:
+ *
+ * STREAM-START(utf-8)
+ * ANCHOR("A")
+ * FLOW-SEQUENCE-START
+ * ALIAS("A")
+ * FLOW-SEQUENCE-END
+ * STREAM-END
+ *
+ * 2. A tagged scalar:
+ *
+ * !!float "3.14" # A good approximation.
+ *
+ * Tokens:
+ *
+ * STREAM-START(utf-8)
+ * TAG("!!","float")
+ * SCALAR("3.14",double-quoted)
+ * STREAM-END
+ *
+ * 3. Various scalar styles:
+ *
+ * --- # Implicit empty plain scalars do not produce tokens.
+ * --- a plain scalar
+ * --- 'a single-quoted scalar'
+ * --- "a double-quoted scalar"
+ * --- |-
+ * a literal scalar
+ * --- >-
+ * a folded
+ * scalar
+ *
+ * Tokens:
+ *
+ * STREAM-START(utf-8)
+ * DOCUMENT-START
+ * DOCUMENT-START
+ * SCALAR("a plain scalar",plain)
+ * DOCUMENT-START
+ * SCALAR("a single-quoted scalar",single-quoted)
+ * DOCUMENT-START
+ * SCALAR("a double-quoted scalar",double-quoted)
+ * DOCUMENT-START
+ * SCALAR("a literal scalar",literal)
+ * DOCUMENT-START
+ * SCALAR("a folded scalar",folded)
+ * STREAM-END
+ *
+ * Now it's time to review collection-related tokens. We will start with
+ * flow collections:
+ *
+ * FLOW-SEQUENCE-START
+ * FLOW-SEQUENCE-END
+ * FLOW-MAPPING-START
+ * FLOW-MAPPING-END
+ * FLOW-ENTRY
+ * KEY
+ * VALUE
+ *
+ * The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and
+ * FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'
+ * correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the
+ * indicators '?' and ':', which are used for denoting mapping keys and values,
+ * are represented by the KEY and VALUE tokens.
+ *
+ * The following examples show flow collections:
+ *
+ * 1. A flow sequence:
+ *
+ * [item 1, item 2, item 3]
+ *
+ * Tokens:
+ *
+ * STREAM-START(utf-8)
+ * FLOW-SEQUENCE-START
+ * SCALAR("item 1",plain)
+ * FLOW-ENTRY
+ * SCALAR("item 2",plain)
+ * FLOW-ENTRY
+ * SCALAR("item 3",plain)
+ * FLOW-SEQUENCE-END
+ * STREAM-END
+ *
+ * 2. A flow mapping:
+ *
+ * {
+ * a simple key: a value, # Note that the KEY token is produced.
+ * ? a complex key: another value,
+ * }
+ *
+ * Tokens:
+ *
+ * STREAM-START(utf-8)
+ * FLOW-MAPPING-START
+ * KEY
+ * SCALAR("a simple key",plain)
+ * VALUE
+ * SCALAR("a value",plain)
+ * FLOW-ENTRY
+ * KEY
+ * SCALAR("a complex key",plain)
+ * VALUE
+ * SCALAR("another value",plain)
+ * FLOW-ENTRY
+ * FLOW-MAPPING-END
+ * STREAM-END
+ *
+ * A simple key is a key which is not denoted by the '?' indicator. Note that
+ * the Scanner still produce the KEY token whenever it encounters a simple key.
+ *
+ * For scanning block collections, the following tokens are used (note that we
+ * repeat KEY and VALUE here):
+ *
+ * BLOCK-SEQUENCE-START
+ * BLOCK-MAPPING-START
+ * BLOCK-END
+ * BLOCK-ENTRY
+ * KEY
+ * VALUE
+ *
+ * The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation
+ * increase that precedes a block collection (cf. the INDENT token in Python).
+ * The token BLOCK-END denote indentation decrease that ends a block collection
+ * (cf. the DEDENT token in Python). However YAML has some syntax pecularities
+ * that makes detections of these tokens more complex.
+ *
+ * The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
+ * '-', '?', and ':' correspondingly.
+ *
+ * The following examples show how the tokens BLOCK-SEQUENCE-START,
+ * BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
+ *
+ * 1. Block sequences:
+ *
+ * - item 1
+ * - item 2
+ * -
+ * - item 3.1
+ * - item 3.2
+ * -
+ * key 1: value 1
+ * key 2: value 2
+ *
+ * Tokens:
+ *
+ * STREAM-START(utf-8)
+ * BLOCK-SEQUENCE-START
+ * BLOCK-ENTRY
+ * SCALAR("item 1",plain)
+ * BLOCK-ENTRY
+ * SCALAR("item 2",plain)
+ * BLOCK-ENTRY
+ * BLOCK-SEQUENCE-START
+ * BLOCK-ENTRY
+ * SCALAR("item 3.1",plain)
+ * BLOCK-ENTRY
+ * SCALAR("item 3.2",plain)
+ * BLOCK-END
+ * BLOCK-ENTRY
+ * BLOCK-MAPPING-START
+ * KEY
+ * SCALAR("key 1",plain)
+ * VALUE
+ * SCALAR("value 1",plain)
+ * KEY
+ * SCALAR("key 2",plain)
+ * VALUE
+ * SCALAR("value 2",plain)
+ * BLOCK-END
+ * BLOCK-END
+ * STREAM-END
+ *
+ * 2. Block mappings:
+ *
+ * a simple key: a value # The KEY token is produced here.
+ * ? a complex key
+ * : another value
+ * a mapping:
+ * key 1: value 1
+ * key 2: value 2
+ * a sequence:
+ * - item 1
+ * - item 2
+ *
+ * Tokens:
+ *
+ * STREAM-START(utf-8)
+ * BLOCK-MAPPING-START
+ * KEY
+ * SCALAR("a simple key",plain)
+ * VALUE
+ * SCALAR("a value",plain)
+ * KEY
+ * SCALAR("a complex key",plain)
+ * VALUE
+ * SCALAR("another value",plain)
+ * KEY
+ * SCALAR("a mapping",plain)
+ * BLOCK-MAPPING-START
+ * KEY
+ * SCALAR("key 1",plain)
+ * VALUE
+ * SCALAR("value 1",plain)
+ * KEY
+ * SCALAR("key 2",plain)
+ * VALUE
+ * SCALAR("value 2",plain)
+ * BLOCK-END
+ * KEY
+ * SCALAR("a sequence",plain)
+ * VALUE
+ * BLOCK-SEQUENCE-START
+ * BLOCK-ENTRY
+ * SCALAR("item 1",plain)
+ * BLOCK-ENTRY
+ * SCALAR("item 2",plain)
+ * BLOCK-END
+ * BLOCK-END
+ * STREAM-END
+ *
+ * YAML does not always require to start a new block collection from a new
+ * line. If the current line contains only '-', '?', and ':' indicators, a new
+ * block collection may start at the current line. The following examples
+ * illustrate this case:
+ *
+ * 1. Collections in a sequence:
+ *
+ * - - item 1
+ * - item 2
+ * - key 1: value 1
+ * key 2: value 2
+ * - ? complex key
+ * : complex value
+ *
+ * Tokens:
+ *
+ * STREAM-START(utf-8)
+ * BLOCK-SEQUENCE-START
+ * BLOCK-ENTRY
+ * BLOCK-SEQUENCE-START
+ * BLOCK-ENTRY
+ * SCALAR("item 1",plain)
+ * BLOCK-ENTRY
+ * SCALAR("item 2",plain)
+ * BLOCK-END
+ * BLOCK-ENTRY
+ * BLOCK-MAPPING-START
+ * KEY
+ * SCALAR("key 1",plain)
+ * VALUE
+ * SCALAR("value 1",plain)
+ * KEY
+ * SCALAR("key 2",plain)
+ * VALUE
+ * SCALAR("value 2",plain)
+ * BLOCK-END
+ * BLOCK-ENTRY
+ * BLOCK-MAPPING-START
+ * KEY
+ * SCALAR("complex key")
+ * VALUE
+ * SCALAR("complex value")
+ * BLOCK-END
+ * BLOCK-END
+ * STREAM-END
+ *
+ * 2. Collections in a mapping:
+ *
+ * ? a sequence
+ * : - item 1
+ * - item 2
+ * ? a mapping
+ * : key 1: value 1
+ * key 2: value 2
+ *
+ * Tokens:
+ *
+ * STREAM-START(utf-8)
+ * BLOCK-MAPPING-START
+ * KEY
+ * SCALAR("a sequence",plain)
+ * VALUE
+ * BLOCK-SEQUENCE-START
+ * BLOCK-ENTRY
+ * SCALAR("item 1",plain)
+ * BLOCK-ENTRY
+ * SCALAR("item 2",plain)
+ * BLOCK-END
+ * KEY
+ * SCALAR("a mapping",plain)
+ * VALUE
+ * BLOCK-MAPPING-START
+ * KEY
+ * SCALAR("key 1",plain)
+ * VALUE
+ * SCALAR("value 1",plain)
+ * KEY
+ * SCALAR("key 2",plain)
+ * VALUE
+ * SCALAR("value 2",plain)
+ * BLOCK-END
+ * BLOCK-END
+ * STREAM-END
+ *
+ * YAML also permits non-indented sequences if they are included into a block
+ * mapping. In this case, the token BLOCK-SEQUENCE-START is not produced:
+ *
+ * key:
+ * - item 1 # BLOCK-SEQUENCE-START is NOT produced here.
+ * - item 2
+ *
+ * Tokens:
+ *
+ * STREAM-START(utf-8)
+ * BLOCK-MAPPING-START
+ * KEY
+ * SCALAR("key",plain)
+ * VALUE
+ * BLOCK-ENTRY
+ * SCALAR("item 1",plain)
+ * BLOCK-ENTRY
+ * SCALAR("item 2",plain)
+ * BLOCK-END
+ */
+
+#include "libyaml/yaml_private.h"
+
+/*
+ * Ensure that the buffer contains the required number of characters.
+ * Return 1 on success, 0 on failure (reader error or memory error).
+ */
+
+#define CACHE(parser,length) \
+ (parser->unread >= (length) \
+ ? 1 \
+ : yaml_parser_update_buffer(parser, (length)))
+
+/*
+ * Advance the buffer pointer.
+ */
+
+#define SKIP(parser) \
+ (parser->mark.index ++, \
+ parser->mark.column ++, \
+ parser->unread --, \
+ parser->buffer.pointer += WIDTH(parser->buffer))
+
+#define SKIP_LINE(parser) \
+ (IS_CRLF(parser->buffer) ? \
+ (parser->mark.index += 2, \
+ parser->mark.column = 0, \
+ parser->mark.line ++, \
+ parser->unread -= 2, \
+ parser->buffer.pointer += 2) : \
+ IS_BREAK(parser->buffer) ? \
+ (parser->mark.index ++, \
+ parser->mark.column = 0, \
+ parser->mark.line ++, \
+ parser->unread --, \
+ parser->buffer.pointer += WIDTH(parser->buffer)) : 0)
+
+/*
+ * Copy a character to a string buffer and advance pointers.
+ */
+
+#define READ(parser,string) \
+ (STRING_EXTEND(parser,string) ? \
+ (COPY(string,parser->buffer), \
+ parser->mark.index ++, \
+ parser->mark.column ++, \
+ parser->unread --, \
+ 1) : 0)
+
+/*
+ * Copy a line break character to a string buffer and advance pointers.
+ */
+
+#define READ_LINE(parser,string) \
+ (STRING_EXTEND(parser,string) ? \
+ (((CHECK_AT(parser->buffer,'\r',0) \
+ && CHECK_AT(parser->buffer,'\n',1)) ? /* CR LF -> LF */ \
+ (*((string).pointer++) = (yaml_char_t) '\n', \
+ parser->buffer.pointer += 2, \
+ parser->mark.index += 2, \
+ parser->mark.column = 0, \
+ parser->mark.line ++, \
+ parser->unread -= 2) : \
+ (CHECK_AT(parser->buffer,'\r',0) \
+ || CHECK_AT(parser->buffer,'\n',0)) ? /* CR|LF -> LF */ \
+ (*((string).pointer++) = (yaml_char_t) '\n', \
+ parser->buffer.pointer ++, \
+ parser->mark.index ++, \
+ parser->mark.column = 0, \
+ parser->mark.line ++, \
+ parser->unread --) : \
+ (CHECK_AT(parser->buffer,'\xC2',0) \
+ && CHECK_AT(parser->buffer,'\x85',1)) ? /* NEL -> LF */ \
+ (*((string).pointer++) = (yaml_char_t) '\n', \
+ parser->buffer.pointer += 2, \
+ parser->mark.index ++, \
+ parser->mark.column = 0, \
+ parser->mark.line ++, \
+ parser->unread --) : \
+ (CHECK_AT(parser->buffer,'\xE2',0) && \
+ CHECK_AT(parser->buffer,'\x80',1) && \
+ (CHECK_AT(parser->buffer,'\xA8',2) || \
+ CHECK_AT(parser->buffer,'\xA9',2))) ? /* LS|PS -> LS|PS */ \
+ (*((string).pointer++) = *(parser->buffer.pointer++), \
+ *((string).pointer++) = *(parser->buffer.pointer++), \
+ *((string).pointer++) = *(parser->buffer.pointer++), \
+ parser->mark.index ++, \
+ parser->mark.column = 0, \
+ parser->mark.line ++, \
+ parser->unread --) : 0), \
+ 1) : 0)
+
+/*
+ * Public API declarations.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token);
+
+/*
+ * Error handling.
+ */
+
+static int
+yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context,
+ yaml_mark_t context_mark, const char *problem);
+
+/*
+ * High-level token API.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
+
+static int
+yaml_parser_fetch_next_token(yaml_parser_t *parser);
+
+/*
+ * Potential simple keys.
+ */
+
+static int
+yaml_parser_stale_simple_keys(yaml_parser_t *parser);
+
+static int
+yaml_parser_save_simple_key(yaml_parser_t *parser);
+
+static int
+yaml_parser_remove_simple_key(yaml_parser_t *parser);
+
+static int
+yaml_parser_increase_flow_level(yaml_parser_t *parser);
+
+static int
+yaml_parser_decrease_flow_level(yaml_parser_t *parser);
+
+/*
+ * Indentation treatment.
+ */
+
+static int
+yaml_parser_roll_indent(yaml_parser_t *parser, int column,
+ int number, yaml_token_type_t type, yaml_mark_t mark);
+
+static int
+yaml_parser_unroll_indent(yaml_parser_t *parser, int column);
+
+/*
+ * Token fetchers.
+ */
+
+static int
+yaml_parser_fetch_stream_start(yaml_parser_t *parser);
+
+static int
+yaml_parser_fetch_stream_end(yaml_parser_t *parser);
+
+static int
+yaml_parser_fetch_directive(yaml_parser_t *parser);
+
+static int
+yaml_parser_fetch_document_indicator(yaml_parser_t *parser,
+ yaml_token_type_t type);
+
+static int
+yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser,
+ yaml_token_type_t type);
+
+static int
+yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser,
+ yaml_token_type_t type);
+
+static int
+yaml_parser_fetch_flow_entry(yaml_parser_t *parser);
+
+static int
+yaml_parser_fetch_block_entry(yaml_parser_t *parser);
+
+static int
+yaml_parser_fetch_key(yaml_parser_t *parser);
+
+static int
+yaml_parser_fetch_value(yaml_parser_t *parser);
+
+static int
+yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type);
+
+static int
+yaml_parser_fetch_tag(yaml_parser_t *parser);
+
+static int
+yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal);
+
+static int
+yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single);
+
+static int
+yaml_parser_fetch_plain_scalar(yaml_parser_t *parser);
+
+/*
+ * Token scanners.
+ */
+
+static int
+yaml_parser_scan_to_next_token(yaml_parser_t *parser);
+
+static int
+yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token);
+
+static int
+yaml_parser_scan_directive_name(yaml_parser_t *parser,
+ yaml_mark_t start_mark, yaml_char_t **name);
+
+static int
+yaml_parser_scan_titleVersion_directive_value(yaml_parser_t *parser,
+ yaml_mark_t start_mark, int *major, int *minor);
+
+static int
+yaml_parser_scan_titleVersion_directive_number(yaml_parser_t *parser,
+ yaml_mark_t start_mark, int *number);
+
+static int
+yaml_parser_scan_tag_directive_value(yaml_parser_t *parser,
+ yaml_mark_t mark, yaml_char_t **handle, yaml_char_t **prefix);
+
+static int
+yaml_parser_scan_anchor(yaml_parser_t *parser, yaml_token_t *token,
+ yaml_token_type_t type);
+
+static int
+yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token);
+
+static int
+yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive,
+ yaml_mark_t start_mark, yaml_char_t **handle);
+
+static int
+yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
+ yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri);
+
+static int
+yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive,
+ yaml_mark_t start_mark, yaml_string_t *string);
+
+static int
+yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token,
+ int literal);
+
+static int
+yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser,
+ int *indent, yaml_string_t *breaks,
+ yaml_mark_t start_mark, yaml_mark_t *end_mark);
+
+static int
+yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token,
+ int single);
+
+static int
+yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token);
+
+/*
+ * Get the next token.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token)
+{
+ assert(parser); /* Non-NULL parser object is expected. */
+ assert(token); /* Non-NULL token object is expected. */
+
+ /* Erase the token object. */
+
+ memset(token, 0, sizeof(yaml_token_t));
+
+ /* No tokens after STREAM-END or error. */
+
+ if (parser->stream_end_produced || parser->error) {
+ return 1;
+ }
+
+ /* Ensure that the tokens queue contains enough tokens. */
+
+ if (!parser->token_available) {
+ if (!yaml_parser_fetch_more_tokens(parser))
+ return 0;
+ }
+
+ /* Fetch the next token from the queue. */
+
+ *token = DEQUEUE(parser, parser->tokens);
+ parser->token_available = 0;
+ parser->tokens_parsed ++;
+
+ if (token->type == YAML_STREAM_END_TOKEN) {
+ parser->stream_end_produced = 1;
+ }
+
+ return 1;
+}
+
+/*
+ * Set the scanner error and return 0.
+ */
+
+static int
+yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context,
+ yaml_mark_t context_mark, const char *problem)
+{
+ parser->error = YAML_SCANNER_ERROR;
+ parser->context = context;
+ parser->context_mark = context_mark;
+ parser->problem = problem;
+ parser->problem_mark = parser->mark;
+
+ return 0;
+}
+
+/*
+ * Ensure that the tokens queue contains at least one token which can be
+ * returned to the Parser.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_fetch_more_tokens(yaml_parser_t *parser)
+{
+ int need_more_tokens;
+
+ /* While we need more tokens to fetch, do it. */
+
+ while (1)
+ {
+ /*
+ * Check if we really need to fetch more tokens.
+ */
+
+ need_more_tokens = 0;
+
+ if (parser->tokens.head == parser->tokens.tail)
+ {
+ /* Queue is empty. */
+
+ need_more_tokens = 1;
+ }
+ else
+ {
+ yaml_simple_key_t *simple_key;
+
+ /* Check if any potential simple key may occupy the head position. */
+
+ if (!yaml_parser_stale_simple_keys(parser))
+ return 0;
+
+ for (simple_key = parser->simple_keys.start;
+ simple_key != parser->simple_keys.top; simple_key++) {
+ if (simple_key->possible
+ && simple_key->token_number == parser->tokens_parsed) {
+ need_more_tokens = 1;
+ break;
+ }
+ }
+ }
+
+ /* We are finished. */
+
+ if (!need_more_tokens)
+ break;
+
+ /* Fetch the next token. */
+
+ if (!yaml_parser_fetch_next_token(parser))
+ return 0;
+ }
+
+ parser->token_available = 1;
+
+ return 1;
+}
+
+/*
+ * The dispatcher for token fetchers.
+ */
+
+static int
+yaml_parser_fetch_next_token(yaml_parser_t *parser)
+{
+ /* Ensure that the buffer is initialized. */
+
+ if (!CACHE(parser, 1))
+ return 0;
+
+ /* Check if we just started scanning. Fetch STREAM-START then. */
+
+ if (!parser->stream_start_produced)
+ return yaml_parser_fetch_stream_start(parser);
+
+ /* Eat whitespaces and comments until we reach the next token. */
+
+ if (!yaml_parser_scan_to_next_token(parser))
+ return 0;
+
+ /* Remove obsolete potential simple keys. */
+
+ if (!yaml_parser_stale_simple_keys(parser))
+ return 0;
+
+ /* Check the indentation level against the current column. */
+
+ if (!yaml_parser_unroll_indent(parser, parser->mark.column))
+ return 0;
+
+ /*
+ * Ensure that the buffer contains at least 4 characters. 4 is the length
+ * of the longest indicators ('--- ' and '... ').
+ */
+
+ if (!CACHE(parser, 4))
+ return 0;
+
+ /* Is it the end of the stream? */
+
+ if (IS_Z(parser->buffer))
+ return yaml_parser_fetch_stream_end(parser);
+
+ /* Is it a directive? */
+
+ if (parser->mark.column == 0 && CHECK(parser->buffer, '%'))
+ return yaml_parser_fetch_directive(parser);
+
+ /* Is it the document start indicator? */
+
+ if (parser->mark.column == 0
+ && CHECK_AT(parser->buffer, '-', 0)
+ && CHECK_AT(parser->buffer, '-', 1)
+ && CHECK_AT(parser->buffer, '-', 2)
+ && IS_BLANKZ_AT(parser->buffer, 3))
+ return yaml_parser_fetch_document_indicator(parser,
+ YAML_DOCUMENT_START_TOKEN);
+
+ /* Is it the document end indicator? */
+
+ if (parser->mark.column == 0
+ && CHECK_AT(parser->buffer, '.', 0)
+ && CHECK_AT(parser->buffer, '.', 1)
+ && CHECK_AT(parser->buffer, '.', 2)
+ && IS_BLANKZ_AT(parser->buffer, 3))
+ return yaml_parser_fetch_document_indicator(parser,
+ YAML_DOCUMENT_END_TOKEN);
+
+ /* Is it the flow sequence start indicator? */
+
+ if (CHECK(parser->buffer, '['))
+ return yaml_parser_fetch_flow_collection_start(parser,
+ YAML_FLOW_SEQUENCE_START_TOKEN);
+
+ /* Is it the flow mapping start indicator? */
+
+ if (CHECK(parser->buffer, '{'))
+ return yaml_parser_fetch_flow_collection_start(parser,
+ YAML_FLOW_MAPPING_START_TOKEN);
+
+ /* Is it the flow sequence end indicator? */
+
+ if (CHECK(parser->buffer, ']'))
+ return yaml_parser_fetch_flow_collection_end(parser,
+ YAML_FLOW_SEQUENCE_END_TOKEN);
+
+ /* Is it the flow mapping end indicator? */
+
+ if (CHECK(parser->buffer, '}'))
+ return yaml_parser_fetch_flow_collection_end(parser,
+ YAML_FLOW_MAPPING_END_TOKEN);
+
+ /* Is it the flow entry indicator? */
+
+ if (CHECK(parser->buffer, ','))
+ return yaml_parser_fetch_flow_entry(parser);
+
+ /* Is it the block entry indicator? */
+
+ if (CHECK(parser->buffer, '-') && IS_BLANKZ_AT(parser->buffer, 1))
+ return yaml_parser_fetch_block_entry(parser);
+
+ /* Is it the key indicator? */
+
+ if (CHECK(parser->buffer, '?')
+ && (parser->flow_level || IS_BLANKZ_AT(parser->buffer, 1)))
+ return yaml_parser_fetch_key(parser);
+
+ /* Is it the value indicator? */
+
+ if (CHECK(parser->buffer, ':')
+ && (parser->flow_level || IS_BLANKZ_AT(parser->buffer, 1)))
+ return yaml_parser_fetch_value(parser);
+
+ /* Is it an alias? */
+
+ if (CHECK(parser->buffer, '*'))
+ return yaml_parser_fetch_anchor(parser, YAML_ALIAS_TOKEN);
+
+ /* Is it an anchor? */
+
+ if (CHECK(parser->buffer, '&'))
+ return yaml_parser_fetch_anchor(parser, YAML_ANCHOR_TOKEN);
+
+ /* Is it a tag? */
+
+ if (CHECK(parser->buffer, '!'))
+ return yaml_parser_fetch_tag(parser);
+
+ /* Is it a literal scalar? */
+
+ if (CHECK(parser->buffer, '|') && !parser->flow_level)
+ return yaml_parser_fetch_block_scalar(parser, 1);
+
+ /* Is it a folded scalar? */
+
+ if (CHECK(parser->buffer, '>') && !parser->flow_level)
+ return yaml_parser_fetch_block_scalar(parser, 0);
+
+ /* Is it a single-quoted scalar? */
+
+ if (CHECK(parser->buffer, '\''))
+ return yaml_parser_fetch_flow_scalar(parser, 1);
+
+ /* Is it a double-quoted scalar? */
+
+ if (CHECK(parser->buffer, '"'))
+ return yaml_parser_fetch_flow_scalar(parser, 0);
+
+ /*
+ * Is it a plain scalar?
+ *
+ * A plain scalar may start with any non-blank characters except
+ *
+ * '-', '?', ':', ',', '[', ']', '{', '}',
+ * '#', '&', '*', '!', '|', '>', '\'', '\"',
+ * '%', '@', '`'.
+ *
+ * In the block context (and, for the '-' indicator, in the flow context
+ * too), it may also start with the characters
+ *
+ * '-', '?', ':'
+ *
+ * if it is followed by a non-space character.
+ *
+ * The last rule is more restrictive than the specification requires.
+ */
+
+ if (!(IS_BLANKZ(parser->buffer) || CHECK(parser->buffer, '-')
+ || CHECK(parser->buffer, '?') || CHECK(parser->buffer, ':')
+ || CHECK(parser->buffer, ',') || CHECK(parser->buffer, '[')
+ || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '{')
+ || CHECK(parser->buffer, '}') || CHECK(parser->buffer, '#')
+ || CHECK(parser->buffer, '&') || CHECK(parser->buffer, '*')
+ || CHECK(parser->buffer, '!') || CHECK(parser->buffer, '|')
+ || CHECK(parser->buffer, '>') || CHECK(parser->buffer, '\'')
+ || CHECK(parser->buffer, '"') || CHECK(parser->buffer, '%')
+ || CHECK(parser->buffer, '@') || CHECK(parser->buffer, '`')) ||
+ (CHECK(parser->buffer, '-') && !IS_BLANK_AT(parser->buffer, 1)) ||
+ (!parser->flow_level &&
+ (CHECK(parser->buffer, '?') || CHECK(parser->buffer, ':'))
+ && !IS_BLANKZ_AT(parser->buffer, 1)))
+ return yaml_parser_fetch_plain_scalar(parser);
+
+ /*
+ * If we don't determine the token type so far, it is an error.
+ */
+
+ return yaml_parser_set_scanner_error(parser,
+ "while scanning for the next token", parser->mark,
+ "found character that cannot start any token");
+}
+
+/*
+ * Check the list of potential simple keys and remove the positions that
+ * cannot contain simple keys anymore.
+ */
+
+static int
+yaml_parser_stale_simple_keys(yaml_parser_t *parser)
+{
+ yaml_simple_key_t *simple_key;
+
+ /* Check for a potential simple key for each flow level. */
+
+ for (simple_key = parser->simple_keys.start;
+ simple_key != parser->simple_keys.top; simple_key ++)
+ {
+ /*
+ * The specification requires that a simple key
+ *
+ * - is limited to a single line,
+ * - is shorter than 1024 characters.
+ */
+
+ if (simple_key->possible
+ && (simple_key->mark.line < parser->mark.line
+ || simple_key->mark.index+1024 < parser->mark.index)) {
+
+ /* Check if the potential simple key to be removed is required. */
+
+ if (simple_key->required) {
+ return yaml_parser_set_scanner_error(parser,
+ "while scanning a simple key", simple_key->mark,
+ "could not find expected ':'");
+ }
+
+ simple_key->possible = 0;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Check if a simple key may start at the current position and add it if
+ * needed.
+ */
+
+static int
+yaml_parser_save_simple_key(yaml_parser_t *parser)
+{
+ /*
+ * A simple key is required at the current position if the scanner is in
+ * the block context and the current column coincides with the indentation
+ * level.
+ */
+
+ int required = (!parser->flow_level
+ && parser->indent == (int)parser->mark.column);
+
+ /*
+ * A simple key is required only when it is the first token in the current
+ * line. Therefore it is always allowed. But we add a check anyway.
+ */
+
+ assert(parser->simple_key_allowed || !required); /* Impossible. */
+
+ /*
+ * If the current position may start a simple key, save it.
+ */
+
+ if (parser->simple_key_allowed)
+ {
+ yaml_simple_key_t simple_key;
+ simple_key.possible = 1;
+ simple_key.required = required;
+ simple_key.token_number =
+ parser->tokens_parsed + (parser->tokens.tail - parser->tokens.head);
+ simple_key.mark = parser->mark;
+
+ if (!yaml_parser_remove_simple_key(parser)) return 0;
+
+ *(parser->simple_keys.top-1) = simple_key;
+ }
+
+ return 1;
+}
+
+/*
+ * Remove a potential simple key at the current flow level.
+ */
+
+static int
+yaml_parser_remove_simple_key(yaml_parser_t *parser)
+{
+ yaml_simple_key_t *simple_key = parser->simple_keys.top-1;
+
+ if (simple_key->possible)
+ {
+ /* If the key is required, it is an error. */
+
+ if (simple_key->required) {
+ return yaml_parser_set_scanner_error(parser,
+ "while scanning a simple key", simple_key->mark,
+ "could not find expected ':'");
+ }
+ }
+
+ /* Remove the key from the stack. */
+
+ simple_key->possible = 0;
+
+ return 1;
+}
+
+/*
+ * Increase the flow level and resize the simple key list if needed.
+ */
+
+static int
+yaml_parser_increase_flow_level(yaml_parser_t *parser)
+{
+ yaml_simple_key_t empty_simple_key = { 0, 0, 0, { 0, 0, 0 } };
+
+ /* Reset the simple key on the next level. */
+
+ if (!PUSH(parser, parser->simple_keys, empty_simple_key))
+ return 0;
+
+ /* Increase the flow level. */
+
+ parser->flow_level++;
+
+ return 1;
+}
+
+/*
+ * Decrease the flow level.
+ */
+
+static int
+yaml_parser_decrease_flow_level(yaml_parser_t *parser)
+{
+ yaml_simple_key_t dummy_key; /* Used to eliminate a compiler warning. */
+
+ if (parser->flow_level) {
+ parser->flow_level --;
+ dummy_key = POP(parser, parser->simple_keys);
+ }
+
+ return 1;
+}
+
+/*
+ * Push the current indentation level to the stack and set the new level
+ * the current column is greater than the indentation level. In this case,
+ * append or insert the specified token into the token queue.
+ *
+ */
+
+static int
+yaml_parser_roll_indent(yaml_parser_t *parser, int column,
+ int number, yaml_token_type_t type, yaml_mark_t mark)
+{
+ yaml_token_t token;
+
+ /* In the flow context, do nothing. */
+
+ if (parser->flow_level)
+ return 1;
+
+ if (parser->indent < column)
+ {
+ /*
+ * Push the current indentation level to the stack and set the new
+ * indentation level.
+ */
+
+ if (!PUSH(parser, parser->indents, parser->indent))
+ return 0;
+
+ parser->indent = column;
+
+ /* Create a token and insert it into the queue. */
+
+ TOKEN_INIT(token, type, mark, mark);
+
+ if (number == -1) {
+ if (!ENQUEUE(parser, parser->tokens, token))
+ return 0;
+ }
+ else {
+ if (!QUEUE_INSERT(parser,
+ parser->tokens, number - parser->tokens_parsed, token))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Pop indentation levels from the indents stack until the current level
+ * becomes less or equal to the column. For each intendation level, append
+ * the BLOCK-END token.
+ */
+
+
+static int
+yaml_parser_unroll_indent(yaml_parser_t *parser, int column)
+{
+ yaml_token_t token;
+
+ /* In the flow context, do nothing. */
+
+ if (parser->flow_level)
+ return 1;
+
+ /* Loop through the intendation levels in the stack. */
+
+ while (parser->indent > column)
+ {
+ /* Create a token and append it to the queue. */
+
+ TOKEN_INIT(token, YAML_BLOCK_END_TOKEN, parser->mark, parser->mark);
+
+ if (!ENQUEUE(parser, parser->tokens, token))
+ return 0;
+
+ /* Pop the indentation level. */
+
+ parser->indent = POP(parser, parser->indents);
+ }
+
+ return 1;
+}
+
+/*
+ * Initialize the scanner and produce the STREAM-START token.
+ */
+
+static int
+yaml_parser_fetch_stream_start(yaml_parser_t *parser)
+{
+ yaml_simple_key_t simple_key = { 0, 0, 0, { 0, 0, 0 } };
+ yaml_token_t token;
+
+ /* Set the initial indentation. */
+
+ parser->indent = -1;
+
+ /* Initialize the simple key stack. */
+
+ if (!PUSH(parser, parser->simple_keys, simple_key))
+ return 0;
+
+ /* A simple key is allowed at the beginning of the stream. */
+
+ parser->simple_key_allowed = 1;
+
+ /* We have started. */
+
+ parser->stream_start_produced = 1;
+
+ /* Create the STREAM-START token and append it to the queue. */
+
+ STREAM_START_TOKEN_INIT(token, parser->encoding,
+ parser->mark, parser->mark);
+
+ if (!ENQUEUE(parser, parser->tokens, token))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Produce the STREAM-END token and shut down the scanner.
+ */
+
+static int
+yaml_parser_fetch_stream_end(yaml_parser_t *parser)
+{
+ yaml_token_t token;
+
+ /* Force new line. */
+
+ if (parser->mark.column != 0) {
+ parser->mark.column = 0;
+ parser->mark.line ++;
+ }
+
+ /* Reset the indentation level. */
+
+ if (!yaml_parser_unroll_indent(parser, -1))
+ return 0;
+
+ /* Reset simple keys. */
+
+ if (!yaml_parser_remove_simple_key(parser))
+ return 0;
+
+ parser->simple_key_allowed = 0;
+
+ /* Create the STREAM-END token and append it to the queue. */
+
+ STREAM_END_TOKEN_INIT(token, parser->mark, parser->mark);
+
+ if (!ENQUEUE(parser, parser->tokens, token))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Produce a titleVersion-DIRECTIVE or TAG-DIRECTIVE token.
+ */
+
+static int
+yaml_parser_fetch_directive(yaml_parser_t *parser)
+{
+ yaml_token_t token;
+
+ /* Reset the indentation level. */
+
+ if (!yaml_parser_unroll_indent(parser, -1))
+ return 0;
+
+ /* Reset simple keys. */
+
+ if (!yaml_parser_remove_simple_key(parser))
+ return 0;
+
+ parser->simple_key_allowed = 0;
+
+ /* Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. */
+
+ if (!yaml_parser_scan_directive(parser, &token))
+ return 0;
+
+ /* Append the token to the queue. */
+
+ if (!ENQUEUE(parser, parser->tokens, token)) {
+ yaml_token_delete(&token);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Produce the DOCUMENT-START or DOCUMENT-END token.
+ */
+
+static int
+yaml_parser_fetch_document_indicator(yaml_parser_t *parser,
+ yaml_token_type_t type)
+{
+ yaml_mark_t start_mark, end_mark;
+ yaml_token_t token;
+
+ /* Reset the indentation level. */
+
+ if (!yaml_parser_unroll_indent(parser, -1))
+ return 0;
+
+ /* Reset simple keys. */
+
+ if (!yaml_parser_remove_simple_key(parser))
+ return 0;
+
+ parser->simple_key_allowed = 0;
+
+ /* Consume the token. */
+
+ start_mark = parser->mark;
+
+ SKIP(parser);
+ SKIP(parser);
+ SKIP(parser);
+
+ end_mark = parser->mark;
+
+ /* Create the DOCUMENT-START or DOCUMENT-END token. */
+
+ TOKEN_INIT(token, type, start_mark, end_mark);
+
+ /* Append the token to the queue. */
+
+ if (!ENQUEUE(parser, parser->tokens, token))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
+ */
+
+static int
+yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser,
+ yaml_token_type_t type)
+{
+ yaml_mark_t start_mark, end_mark;
+ yaml_token_t token;
+
+ /* The indicators '[' and '{' may start a simple key. */
+
+ if (!yaml_parser_save_simple_key(parser))
+ return 0;
+
+ /* Increase the flow level. */
+
+ if (!yaml_parser_increase_flow_level(parser))
+ return 0;
+
+ /* A simple key may follow the indicators '[' and '{'. */
+
+ parser->simple_key_allowed = 1;
+
+ /* Consume the token. */
+
+ start_mark = parser->mark;
+ SKIP(parser);
+ end_mark = parser->mark;
+
+ /* Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. */
+
+ TOKEN_INIT(token, type, start_mark, end_mark);
+
+ /* Append the token to the queue. */
+
+ if (!ENQUEUE(parser, parser->tokens, token))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
+ */
+
+static int
+yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser,
+ yaml_token_type_t type)
+{
+ yaml_mark_t start_mark, end_mark;
+ yaml_token_t token;
+
+ /* Reset any potential simple key on the current flow level. */
+
+ if (!yaml_parser_remove_simple_key(parser))
+ return 0;
+
+ /* Decrease the flow level. */
+
+ if (!yaml_parser_decrease_flow_level(parser))
+ return 0;
+
+ /* No simple keys after the indicators ']' and '}'. */
+
+ parser->simple_key_allowed = 0;
+
+ /* Consume the token. */
+
+ start_mark = parser->mark;
+ SKIP(parser);
+ end_mark = parser->mark;
+
+ /* Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. */
+
+ TOKEN_INIT(token, type, start_mark, end_mark);
+
+ /* Append the token to the queue. */
+
+ if (!ENQUEUE(parser, parser->tokens, token))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Produce the FLOW-ENTRY token.
+ */
+
+static int
+yaml_parser_fetch_flow_entry(yaml_parser_t *parser)
+{
+ yaml_mark_t start_mark, end_mark;
+ yaml_token_t token;
+
+ /* Reset any potential simple keys on the current flow level. */
+
+ if (!yaml_parser_remove_simple_key(parser))
+ return 0;
+
+ /* Simple keys are allowed after ','. */
+
+ parser->simple_key_allowed = 1;
+
+ /* Consume the token. */
+
+ start_mark = parser->mark;
+ SKIP(parser);
+ end_mark = parser->mark;
+
+ /* Create the FLOW-ENTRY token and append it to the queue. */
+
+ TOKEN_INIT(token, YAML_FLOW_ENTRY_TOKEN, start_mark, end_mark);
+
+ if (!ENQUEUE(parser, parser->tokens, token))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Produce the BLOCK-ENTRY token.
+ */
+
+static int
+yaml_parser_fetch_block_entry(yaml_parser_t *parser)
+{
+ yaml_mark_t start_mark, end_mark;
+ yaml_token_t token;
+
+ /* Check if the scanner is in the block context. */
+
+ if (!parser->flow_level)
+ {
+ /* Check if we are allowed to start a new entry. */
+
+ if (!parser->simple_key_allowed) {
+ return yaml_parser_set_scanner_error(parser, NULL, parser->mark,
+ "block sequence entries are not allowed in this context");
+ }
+
+ /* Add the BLOCK-SEQUENCE-START token if needed. */
+
+ if (!yaml_parser_roll_indent(parser, parser->mark.column, -1,
+ YAML_BLOCK_SEQUENCE_START_TOKEN, parser->mark))
+ return 0;
+ }
+ else
+ {
+ /*
+ * It is an error for the '-' indicator to occur in the flow context,
+ * but we let the Parser detect and report about it because the Parser
+ * is able to point to the context.
+ */
+ }
+
+ /* Reset any potential simple keys on the current flow level. */
+
+ if (!yaml_parser_remove_simple_key(parser))
+ return 0;
+
+ /* Simple keys are allowed after '-'. */
+
+ parser->simple_key_allowed = 1;
+
+ /* Consume the token. */
+
+ start_mark = parser->mark;
+ SKIP(parser);
+ end_mark = parser->mark;
+
+ /* Create the BLOCK-ENTRY token and append it to the queue. */
+
+ TOKEN_INIT(token, YAML_BLOCK_ENTRY_TOKEN, start_mark, end_mark);
+
+ if (!ENQUEUE(parser, parser->tokens, token))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Produce the KEY token.
+ */
+
+static int
+yaml_parser_fetch_key(yaml_parser_t *parser)
+{
+ yaml_mark_t start_mark, end_mark;
+ yaml_token_t token;
+
+ /* In the block context, additional checks are required. */
+
+ if (!parser->flow_level)
+ {
+ /* Check if we are allowed to start a new key (not nessesary simple). */
+
+ if (!parser->simple_key_allowed) {
+ return yaml_parser_set_scanner_error(parser, NULL, parser->mark,
+ "mapping keys are not allowed in this context");
+ }
+
+ /* Add the BLOCK-MAPPING-START token if needed. */
+
+ if (!yaml_parser_roll_indent(parser, parser->mark.column, -1,
+ YAML_BLOCK_MAPPING_START_TOKEN, parser->mark))
+ return 0;
+ }
+
+ /* Reset any potential simple keys on the current flow level. */
+
+ if (!yaml_parser_remove_simple_key(parser))
+ return 0;
+
+ /* Simple keys are allowed after '?' in the block context. */
+
+ parser->simple_key_allowed = (!parser->flow_level);
+
+ /* Consume the token. */
+
+ start_mark = parser->mark;
+ SKIP(parser);
+ end_mark = parser->mark;
+
+ /* Create the KEY token and append it to the queue. */
+
+ TOKEN_INIT(token, YAML_KEY_TOKEN, start_mark, end_mark);
+
+ if (!ENQUEUE(parser, parser->tokens, token))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Produce the VALUE token.
+ */
+
+static int
+yaml_parser_fetch_value(yaml_parser_t *parser)
+{
+ yaml_mark_t start_mark, end_mark;
+ yaml_token_t token;
+ yaml_simple_key_t *simple_key = parser->simple_keys.top-1;
+
+ /* Have we found a simple key? */
+
+ if (simple_key->possible)
+ {
+
+ /* Create the KEY token and insert it into the queue. */
+
+ TOKEN_INIT(token, YAML_KEY_TOKEN, simple_key->mark, simple_key->mark);
+
+ if (!QUEUE_INSERT(parser, parser->tokens,
+ simple_key->token_number - parser->tokens_parsed, token))
+ return 0;
+
+ /* In the block context, we may need to add the BLOCK-MAPPING-START token. */
+
+ if (!yaml_parser_roll_indent(parser, simple_key->mark.column,
+ simple_key->token_number,
+ YAML_BLOCK_MAPPING_START_TOKEN, simple_key->mark))
+ return 0;
+
+ /* Remove the simple key. */
+
+ simple_key->possible = 0;
+
+ /* A simple key cannot follow another simple key. */
+
+ parser->simple_key_allowed = 0;
+ }
+ else
+ {
+ /* The ':' indicator follows a complex key. */
+
+ /* In the block context, extra checks are required. */
+
+ if (!parser->flow_level)
+ {
+ /* Check if we are allowed to start a complex value. */
+
+ if (!parser->simple_key_allowed) {
+ return yaml_parser_set_scanner_error(parser, NULL, parser->mark,
+ "mapping values are not allowed in this context");
+ }
+
+ /* Add the BLOCK-MAPPING-START token if needed. */
+
+ if (!yaml_parser_roll_indent(parser, parser->mark.column, -1,
+ YAML_BLOCK_MAPPING_START_TOKEN, parser->mark))
+ return 0;
+ }
+
+ /* Simple keys after ':' are allowed in the block context. */
+
+ parser->simple_key_allowed = (!parser->flow_level);
+ }
+
+ /* Consume the token. */
+
+ start_mark = parser->mark;
+ SKIP(parser);
+ end_mark = parser->mark;
+
+ /* Create the VALUE token and append it to the queue. */
+
+ TOKEN_INIT(token, YAML_VALUE_TOKEN, start_mark, end_mark);
+
+ if (!ENQUEUE(parser, parser->tokens, token))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Produce the ALIAS or ANCHOR token.
+ */
+
+static int
+yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type)
+{
+ yaml_token_t token;
+
+ /* An anchor or an alias could be a simple key. */
+
+ if (!yaml_parser_save_simple_key(parser))
+ return 0;
+
+ /* A simple key cannot follow an anchor or an alias. */
+
+ parser->simple_key_allowed = 0;
+
+ /* Create the ALIAS or ANCHOR token and append it to the queue. */
+
+ if (!yaml_parser_scan_anchor(parser, &token, type))
+ return 0;
+
+ if (!ENQUEUE(parser, parser->tokens, token)) {
+ yaml_token_delete(&token);
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Produce the TAG token.
+ */
+
+static int
+yaml_parser_fetch_tag(yaml_parser_t *parser)
+{
+ yaml_token_t token;
+
+ /* A tag could be a simple key. */
+
+ if (!yaml_parser_save_simple_key(parser))
+ return 0;
+
+ /* A simple key cannot follow a tag. */
+
+ parser->simple_key_allowed = 0;
+
+ /* Create the TAG token and append it to the queue. */
+
+ if (!yaml_parser_scan_tag(parser, &token))
+ return 0;
+
+ if (!ENQUEUE(parser, parser->tokens, token)) {
+ yaml_token_delete(&token);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
+ */
+
+static int
+yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal)
+{
+ yaml_token_t token;
+
+ /* Remove any potential simple keys. */
+
+ if (!yaml_parser_remove_simple_key(parser))
+ return 0;
+
+ /* A simple key may follow a block scalar. */
+
+ parser->simple_key_allowed = 1;
+
+ /* Create the SCALAR token and append it to the queue. */
+
+ if (!yaml_parser_scan_block_scalar(parser, &token, literal))
+ return 0;
+
+ if (!ENQUEUE(parser, parser->tokens, token)) {
+ yaml_token_delete(&token);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
+ */
+
+static int
+yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single)
+{
+ yaml_token_t token;
+
+ /* A plain scalar could be a simple key. */
+
+ if (!yaml_parser_save_simple_key(parser))
+ return 0;
+
+ /* A simple key cannot follow a flow scalar. */
+
+ parser->simple_key_allowed = 0;
+
+ /* Create the SCALAR token and append it to the queue. */
+
+ if (!yaml_parser_scan_flow_scalar(parser, &token, single))
+ return 0;
+
+ if (!ENQUEUE(parser, parser->tokens, token)) {
+ yaml_token_delete(&token);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Produce the SCALAR(...,plain) token.
+ */
+
+static int
+yaml_parser_fetch_plain_scalar(yaml_parser_t *parser)
+{
+ yaml_token_t token;
+
+ /* A plain scalar could be a simple key. */
+
+ if (!yaml_parser_save_simple_key(parser))
+ return 0;
+
+ /* A simple key cannot follow a flow scalar. */
+
+ parser->simple_key_allowed = 0;
+
+ /* Create the SCALAR token and append it to the queue. */
+
+ if (!yaml_parser_scan_plain_scalar(parser, &token))
+ return 0;
+
+ if (!ENQUEUE(parser, parser->tokens, token)) {
+ yaml_token_delete(&token);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Eat whitespaces and comments until the next token is found.
+ */
+
+static int
+yaml_parser_scan_to_next_token(yaml_parser_t *parser)
+{
+ /* Until the next token is not found. */
+
+ while (1)
+ {
+ /* Allow the BOM mark to start a line. */
+
+ if (!CACHE(parser, 1)) return 0;
+
+ if (parser->mark.column == 0 && IS_BOM(parser->buffer))
+ SKIP(parser);
+
+ /*
+ * Eat whitespaces.
+ *
+ * Tabs are allowed:
+ *
+ * - in the flow context;
+ * - in the block context, but not at the beginning of the line or
+ * after '-', '?', or ':' (complex value).
+ */
+
+ if (!CACHE(parser, 1)) return 0;
+
+ while (CHECK(parser->buffer,' ') ||
+ ((parser->flow_level || !parser->simple_key_allowed) &&
+ CHECK(parser->buffer, '\t'))) {
+ SKIP(parser);
+ if (!CACHE(parser, 1)) return 0;
+ }
+
+ /* Eat a comment until a line break. */
+
+ if (CHECK(parser->buffer, '#')) {
+ while (!IS_BREAKZ(parser->buffer)) {
+ SKIP(parser);
+ if (!CACHE(parser, 1)) return 0;
+ }
+ }
+
+ /* If it is a line break, eat it. */
+
+ if (IS_BREAK(parser->buffer))
+ {
+ if (!CACHE(parser, 2)) return 0;
+ SKIP_LINE(parser);
+
+ /* In the block context, a new line may start a simple key. */
+
+ if (!parser->flow_level) {
+ parser->simple_key_allowed = 1;
+ }
+ }
+ else
+ {
+ /* We have found a token. */
+
+ break;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
+ *
+ * Scope:
+ * %YAML 1.1 # a comment \n
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * %TAG !yaml! tag:yaml.org,2002: \n
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ */
+
+int
+yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token)
+{
+ yaml_mark_t start_mark, end_mark;
+ yaml_char_t *name = NULL;
+ int major, minor;
+ yaml_char_t *handle = NULL, *prefix = NULL;
+
+ /* Eat '%'. */
+
+ start_mark = parser->mark;
+
+ SKIP(parser);
+
+ /* Scan the directive name. */
+
+ if (!yaml_parser_scan_directive_name(parser, start_mark, &name))
+ goto error;
+
+ /* Is it a YAML directive? */
+
+ if (strcmp((char *)name, "YAML") == 0)
+ {
+ /* Scan the titleVersion directive value. */
+
+ if (!yaml_parser_scan_titleVersion_directive_value(parser, start_mark,
+ &major, &minor))
+ goto error;
+
+ end_mark = parser->mark;
+
+ /* Create a titleVersion-DIRECTIVE token. */
+
+ titleVersion_DIRECTIVE_TOKEN_INIT(*token, major, minor,
+ start_mark, end_mark);
+ }
+
+ /* Is it a TAG directive? */
+
+ else if (strcmp((char *)name, "TAG") == 0)
+ {
+ /* Scan the TAG directive value. */
+
+ if (!yaml_parser_scan_tag_directive_value(parser, start_mark,
+ &handle, &prefix))
+ goto error;
+
+ end_mark = parser->mark;
+
+ /* Create a TAG-DIRECTIVE token. */
+
+ TAG_DIRECTIVE_TOKEN_INIT(*token, handle, prefix,
+ start_mark, end_mark);
+ }
+
+ /* Unknown directive. */
+
+ else
+ {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "found uknown directive name");
+ goto error;
+ }
+
+ /* Eat the rest of the line including any comments. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ while (IS_BLANK(parser->buffer)) {
+ SKIP(parser);
+ if (!CACHE(parser, 1)) goto error;
+ }
+
+ if (CHECK(parser->buffer, '#')) {
+ while (!IS_BREAKZ(parser->buffer)) {
+ SKIP(parser);
+ if (!CACHE(parser, 1)) goto error;
+ }
+ }
+
+ /* Check if we are at the end of the line. */
+
+ if (!IS_BREAKZ(parser->buffer)) {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "did not find expected comment or line break");
+ goto error;
+ }
+
+ /* Eat a line break. */
+
+ if (IS_BREAK(parser->buffer)) {
+ if (!CACHE(parser, 2)) goto error;
+ SKIP_LINE(parser);
+ }
+
+ yaml_free(name);
+
+ return 1;
+
+error:
+ yaml_free(prefix);
+ yaml_free(handle);
+ yaml_free(name);
+ return 0;
+}
+
+/*
+ * Scan the directive name.
+ *
+ * Scope:
+ * %YAML 1.1 # a comment \n
+ * ^^^^
+ * %TAG !yaml! tag:yaml.org,2002: \n
+ * ^^^
+ */
+
+static int
+yaml_parser_scan_directive_name(yaml_parser_t *parser,
+ yaml_mark_t start_mark, yaml_char_t **name)
+{
+ yaml_string_t string = NULL_STRING;
+
+ if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
+
+ /* Consume the directive name. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ while (IS_ALPHA(parser->buffer))
+ {
+ if (!READ(parser, string)) goto error;
+ if (!CACHE(parser, 1)) goto error;
+ }
+
+ /* Check if the name is empty. */
+
+ if (string.start == string.pointer) {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "could not find expected directive name");
+ goto error;
+ }
+
+ /* Check for an blank character after the name. */
+
+ if (!IS_BLANKZ(parser->buffer)) {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "found unexpected non-alphabetical character");
+ goto error;
+ }
+
+ *name = string.start;
+
+ return 1;
+
+error:
+ STRING_DEL(parser, string);
+ return 0;
+}
+
+/*
+ * Scan the value of titleVersion-DIRECTIVE.
+ *
+ * Scope:
+ * %YAML 1.1 # a comment \n
+ * ^^^^^^
+ */
+
+static int
+yaml_parser_scan_titleVersion_directive_value(yaml_parser_t *parser,
+ yaml_mark_t start_mark, int *major, int *minor)
+{
+ /* Eat whitespaces. */
+
+ if (!CACHE(parser, 1)) return 0;
+
+ while (IS_BLANK(parser->buffer)) {
+ SKIP(parser);
+ if (!CACHE(parser, 1)) return 0;
+ }
+
+ /* Consume the major titleVersion number. */
+
+ if (!yaml_parser_scan_titleVersion_directive_number(parser, start_mark, major))
+ return 0;
+
+ /* Eat '.'. */
+
+ if (!CHECK(parser->buffer, '.')) {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "did not find expected digit or '.' character");
+ }
+
+ SKIP(parser);
+
+ /* Consume the minor titleVersion number. */
+
+ if (!yaml_parser_scan_titleVersion_directive_number(parser, start_mark, minor))
+ return 0;
+
+ return 1;
+}
+
+#define MAX_NUMBER_LENGTH 9
+
+/*
+ * Scan the titleVersion number of titleVersion-DIRECTIVE.
+ *
+ * Scope:
+ * %YAML 1.1 # a comment \n
+ * ^
+ * %YAML 1.1 # a comment \n
+ * ^
+ */
+
+static int
+yaml_parser_scan_titleVersion_directive_number(yaml_parser_t *parser,
+ yaml_mark_t start_mark, int *number)
+{
+ int value = 0;
+ size_t length = 0;
+
+ /* Repeat while the next character is digit. */
+
+ if (!CACHE(parser, 1)) return 0;
+
+ while (IS_DIGIT(parser->buffer))
+ {
+ /* Check if the number is too long. */
+
+ if (++length > MAX_NUMBER_LENGTH) {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "found extremely long titleVersion number");
+ }
+
+ value = value*10 + AS_DIGIT(parser->buffer);
+
+ SKIP(parser);
+
+ if (!CACHE(parser, 1)) return 0;
+ }
+
+ /* Check if the number was present. */
+
+ if (!length) {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "did not find expected titleVersion number");
+ }
+
+ *number = value;
+
+ return 1;
+}
+
+/*
+ * Scan the value of a TAG-DIRECTIVE token.
+ *
+ * Scope:
+ * %TAG !yaml! tag:yaml.org,2002: \n
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ */
+
+static int
+yaml_parser_scan_tag_directive_value(yaml_parser_t *parser,
+ yaml_mark_t start_mark, yaml_char_t **handle, yaml_char_t **prefix)
+{
+ yaml_char_t *handle_value = NULL;
+ yaml_char_t *prefix_value = NULL;
+
+ /* Eat whitespaces. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ while (IS_BLANK(parser->buffer)) {
+ SKIP(parser);
+ if (!CACHE(parser, 1)) goto error;
+ }
+
+ /* Scan a handle. */
+
+ if (!yaml_parser_scan_tag_handle(parser, 1, start_mark, &handle_value))
+ goto error;
+
+ /* Expect a whitespace. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ if (!IS_BLANK(parser->buffer)) {
+ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
+ start_mark, "did not find expected whitespace");
+ goto error;
+ }
+
+ /* Eat whitespaces. */
+
+ while (IS_BLANK(parser->buffer)) {
+ SKIP(parser);
+ if (!CACHE(parser, 1)) goto error;
+ }
+
+ /* Scan a prefix. */
+
+ if (!yaml_parser_scan_tag_uri(parser, 1, NULL, start_mark, &prefix_value))
+ goto error;
+
+ /* Expect a whitespace or line break. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ if (!IS_BLANKZ(parser->buffer)) {
+ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
+ start_mark, "did not find expected whitespace or line break");
+ goto error;
+ }
+
+ *handle = handle_value;
+ *prefix = prefix_value;
+
+ return 1;
+
+error:
+ yaml_free(handle_value);
+ yaml_free(prefix_value);
+ return 0;
+}
+
+static int
+yaml_parser_scan_anchor(yaml_parser_t *parser, yaml_token_t *token,
+ yaml_token_type_t type)
+{
+ int length = 0;
+ yaml_mark_t start_mark, end_mark;
+ yaml_string_t string = NULL_STRING;
+
+ if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
+
+ /* Eat the indicator character. */
+
+ start_mark = parser->mark;
+
+ SKIP(parser);
+
+ /* Consume the value. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ while (IS_ALPHA(parser->buffer)) {
+ if (!READ(parser, string)) goto error;
+ if (!CACHE(parser, 1)) goto error;
+ length ++;
+ }
+
+ end_mark = parser->mark;
+
+ /*
+ * Check if length of the anchor is greater than 0 and it is followed by
+ * a whitespace character or one of the indicators:
+ *
+ * '?', ':', ',', ']', '}', '%', '@', '`'.
+ */
+
+ if (!length || !(IS_BLANKZ(parser->buffer) || CHECK(parser->buffer, '?')
+ || CHECK(parser->buffer, ':') || CHECK(parser->buffer, ',')
+ || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '}')
+ || CHECK(parser->buffer, '%') || CHECK(parser->buffer, '@')
+ || CHECK(parser->buffer, '`'))) {
+ yaml_parser_set_scanner_error(parser, type == YAML_ANCHOR_TOKEN ?
+ "while scanning an anchor" : "while scanning an alias", start_mark,
+ "did not find expected alphabetic or numeric character");
+ goto error;
+ }
+
+ /* Create a token. */
+
+ if (type == YAML_ANCHOR_TOKEN) {
+ ANCHOR_TOKEN_INIT(*token, string.start, start_mark, end_mark);
+ }
+ else {
+ ALIAS_TOKEN_INIT(*token, string.start, start_mark, end_mark);
+ }
+
+ return 1;
+
+error:
+ STRING_DEL(parser, string);
+ return 0;
+}
+
+/*
+ * Scan a TAG token.
+ */
+
+static int
+yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token)
+{
+ yaml_char_t *handle = NULL;
+ yaml_char_t *suffix = NULL;
+ yaml_mark_t start_mark, end_mark;
+
+ start_mark = parser->mark;
+
+ /* Check if the tag is in the canonical form. */
+
+ if (!CACHE(parser, 2)) goto error;
+
+ if (CHECK_AT(parser->buffer, '<', 1))
+ {
+ /* Set the handle to '' */
+
+ handle = yaml_malloc(1);
+ if (!handle) goto error;
+ handle[0] = '\0';
+
+ /* Eat '!<' */
+
+ SKIP(parser);
+ SKIP(parser);
+
+ /* Consume the tag value. */
+
+ if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix))
+ goto error;
+
+ /* Check for '>' and eat it. */
+
+ if (!CHECK(parser->buffer, '>')) {
+ yaml_parser_set_scanner_error(parser, "while scanning a tag",
+ start_mark, "did not find the expected '>'");
+ goto error;
+ }
+
+ SKIP(parser);
+ }
+ else
+ {
+ /* The tag has either the '!suffix' or the '!handle!suffix' form. */
+
+ /* First, try to scan a handle. */
+
+ if (!yaml_parser_scan_tag_handle(parser, 0, start_mark, &handle))
+ goto error;
+
+ /* Check if it is, indeed, handle. */
+
+ if (handle[0] == '!' && handle[1] != '\0' && handle[strlen((char *)handle)-1] == '!')
+ {
+ /* Scan the suffix now. */
+
+ if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix))
+ goto error;
+ }
+ else
+ {
+ /* It wasn't a handle after all. Scan the rest of the tag. */
+
+ if (!yaml_parser_scan_tag_uri(parser, 0, handle, start_mark, &suffix))
+ goto error;
+
+ /* Set the handle to '!'. */
+
+ yaml_free(handle);
+ handle = yaml_malloc(2);
+ if (!handle) goto error;
+ handle[0] = '!';
+ handle[1] = '\0';
+
+ /*
+ * A special case: the '!' tag. Set the handle to '' and the
+ * suffix to '!'.
+ */
+
+ if (suffix[0] == '\0') {
+ yaml_char_t *tmp = handle;
+ handle = suffix;
+ suffix = tmp;
+ }
+ }
+ }
+
+ /* Check the character which ends the tag. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ if (!IS_BLANKZ(parser->buffer)) {
+ yaml_parser_set_scanner_error(parser, "while scanning a tag",
+ start_mark, "did not find expected whitespace or line break");
+ goto error;
+ }
+
+ end_mark = parser->mark;
+
+ /* Create a token. */
+
+ TAG_TOKEN_INIT(*token, handle, suffix, start_mark, end_mark);
+
+ return 1;
+
+error:
+ yaml_free(handle);
+ yaml_free(suffix);
+ return 0;
+}
+
+/*
+ * Scan a tag handle.
+ */
+
+static int
+yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive,
+ yaml_mark_t start_mark, yaml_char_t **handle)
+{
+ yaml_string_t string = NULL_STRING;
+
+ if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
+
+ /* Check the initial '!' character. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ if (!CHECK(parser->buffer, '!')) {
+ yaml_parser_set_scanner_error(parser, directive ?
+ "while scanning a tag directive" : "while scanning a tag",
+ start_mark, "did not find expected '!'");
+ goto error;
+ }
+
+ /* Copy the '!' character. */
+
+ if (!READ(parser, string)) goto error;
+
+ /* Copy all subsequent alphabetical and numerical characters. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ while (IS_ALPHA(parser->buffer))
+ {
+ if (!READ(parser, string)) goto error;
+ if (!CACHE(parser, 1)) goto error;
+ }
+
+ /* Check if the trailing character is '!' and copy it. */
+
+ if (CHECK(parser->buffer, '!'))
+ {
+ if (!READ(parser, string)) goto error;
+ }
+ else
+ {
+ /*
+ * It's either the '!' tag or not really a tag handle. If it's a %TAG
+ * directive, it's an error. If it's a tag token, it must be a part of
+ * URI.
+ */
+
+ if (directive && !(string.start[0] == '!' && string.start[1] == '\0')) {
+ yaml_parser_set_scanner_error(parser, "while parsing a tag directive",
+ start_mark, "did not find expected '!'");
+ goto error;
+ }
+ }
+
+ *handle = string.start;
+
+ return 1;
+
+error:
+ STRING_DEL(parser, string);
+ return 0;
+}
+
+/*
+ * Scan a tag.
+ */
+
+static int
+yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
+ yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri)
+{
+ size_t length = head ? strlen((char *)head) : 0;
+ yaml_string_t string = NULL_STRING;
+
+ if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
+
+ /* Resize the string to include the head. */
+
+ while (string.end - string.start <= (int)length) {
+ if (!yaml_string_extend(&string.start, &string.pointer, &string.end)) {
+ parser->error = YAML_MEMORY_ERROR;
+ goto error;
+ }
+ }
+
+ /*
+ * Copy the head if needed.
+ *
+ * Note that we don't copy the leading '!' character.
+ */
+
+ if (length > 1) {
+ memcpy(string.start, head+1, length-1);
+ string.pointer += length-1;
+ }
+
+ /* Scan the tag. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ /*
+ * The set of characters that may appear in URI is as follows:
+ *
+ * '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
+ * '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
+ * '%'.
+ */
+
+ while (IS_ALPHA(parser->buffer) || CHECK(parser->buffer, ';')
+ || CHECK(parser->buffer, '/') || CHECK(parser->buffer, '?')
+ || CHECK(parser->buffer, ':') || CHECK(parser->buffer, '@')
+ || CHECK(parser->buffer, '&') || CHECK(parser->buffer, '=')
+ || CHECK(parser->buffer, '+') || CHECK(parser->buffer, '$')
+ || CHECK(parser->buffer, ',') || CHECK(parser->buffer, '.')
+ || CHECK(parser->buffer, '!') || CHECK(parser->buffer, '~')
+ || CHECK(parser->buffer, '*') || CHECK(parser->buffer, '\'')
+ || CHECK(parser->buffer, '(') || CHECK(parser->buffer, ')')
+ || CHECK(parser->buffer, '[') || CHECK(parser->buffer, ']')
+ || CHECK(parser->buffer, '%'))
+ {
+ /* Check if it is a URI-escape sequence. */
+
+ if (CHECK(parser->buffer, '%')) {
+ if (!yaml_parser_scan_uri_escapes(parser,
+ directive, start_mark, &string)) goto error;
+ }
+ else {
+ if (!READ(parser, string)) goto error;
+ }
+
+ length ++;
+ if (!CACHE(parser, 1)) goto error;
+ }
+
+ /* Check if the tag is non-empty. */
+
+ if (!length) {
+ if (!STRING_EXTEND(parser, string))
+ goto error;
+
+ yaml_parser_set_scanner_error(parser, directive ?
+ "while parsing a %TAG directive" : "while parsing a tag",
+ start_mark, "did not find expected tag URI");
+ goto error;
+ }
+
+ *uri = string.start;
+
+ return 1;
+
+error:
+ STRING_DEL(parser, string);
+ return 0;
+}
+
+/*
+ * Decode an URI-escape sequence corresponding to a single UTF-8 character.
+ */
+
+static int
+yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive,
+ yaml_mark_t start_mark, yaml_string_t *string)
+{
+ int width = 0;
+
+ /* Decode the required number of characters. */
+
+ do {
+
+ unsigned char octet = 0;
+
+ /* Check for a URI-escaped octet. */
+
+ if (!CACHE(parser, 3)) return 0;
+
+ if (!(CHECK(parser->buffer, '%')
+ && IS_HEX_AT(parser->buffer, 1)
+ && IS_HEX_AT(parser->buffer, 2))) {
+ return yaml_parser_set_scanner_error(parser, directive ?
+ "while parsing a %TAG directive" : "while parsing a tag",
+ start_mark, "did not find URI escaped octet");
+ }
+
+ /* Get the octet. */
+
+ octet = (AS_HEX_AT(parser->buffer, 1) << 4) + AS_HEX_AT(parser->buffer, 2);
+
+ /* If it is the leading octet, determine the length of the UTF-8 sequence. */
+
+ if (!width)
+ {
+ width = (octet & 0x80) == 0x00 ? 1 :
+ (octet & 0xE0) == 0xC0 ? 2 :
+ (octet & 0xF0) == 0xE0 ? 3 :
+ (octet & 0xF8) == 0xF0 ? 4 : 0;
+ if (!width) {
+ return yaml_parser_set_scanner_error(parser, directive ?
+ "while parsing a %TAG directive" : "while parsing a tag",
+ start_mark, "found an incorrect leading UTF-8 octet");
+ }
+ }
+ else
+ {
+ /* Check if the trailing octet is correct. */
+
+ if ((octet & 0xC0) != 0x80) {
+ return yaml_parser_set_scanner_error(parser, directive ?
+ "while parsing a %TAG directive" : "while parsing a tag",
+ start_mark, "found an incorrect trailing UTF-8 octet");
+ }
+ }
+
+ /* Copy the octet and move the pointers. */
+
+ *(string->pointer++) = octet;
+ SKIP(parser);
+ SKIP(parser);
+ SKIP(parser);
+
+ } while (--width);
+
+ return 1;
+}
+
+/*
+ * Scan a block scalar.
+ */
+
+static int
+yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token,
+ int literal)
+{
+ yaml_mark_t start_mark;
+ yaml_mark_t end_mark;
+ yaml_string_t string = NULL_STRING;
+ yaml_string_t leading_break = NULL_STRING;
+ yaml_string_t trailing_breaks = NULL_STRING;
+ int chomping = 0;
+ int increment = 0;
+ int indent = 0;
+ int leading_blank = 0;
+ int trailing_blank = 0;
+
+ if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
+ if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error;
+ if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error;
+
+ /* Eat the indicator '|' or '>'. */
+
+ start_mark = parser->mark;
+
+ SKIP(parser);
+
+ /* Scan the additional block scalar indicators. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ /* Check for a chomping indicator. */
+
+ if (CHECK(parser->buffer, '+') || CHECK(parser->buffer, '-'))
+ {
+ /* Set the chomping method and eat the indicator. */
+
+ chomping = CHECK(parser->buffer, '+') ? +1 : -1;
+
+ SKIP(parser);
+
+ /* Check for an indentation indicator. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ if (IS_DIGIT(parser->buffer))
+ {
+ /* Check that the intendation is greater than 0. */
+
+ if (CHECK(parser->buffer, '0')) {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found an intendation indicator equal to 0");
+ goto error;
+ }
+
+ /* Get the intendation level and eat the indicator. */
+
+ increment = AS_DIGIT(parser->buffer);
+
+ SKIP(parser);
+ }
+ }
+
+ /* Do the same as above, but in the opposite order. */
+
+ else if (IS_DIGIT(parser->buffer))
+ {
+ if (CHECK(parser->buffer, '0')) {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found an intendation indicator equal to 0");
+ goto error;
+ }
+
+ increment = AS_DIGIT(parser->buffer);
+
+ SKIP(parser);
+
+ if (!CACHE(parser, 1)) goto error;
+
+ if (CHECK(parser->buffer, '+') || CHECK(parser->buffer, '-')) {
+ chomping = CHECK(parser->buffer, '+') ? +1 : -1;
+
+ SKIP(parser);
+ }
+ }
+
+ /* Eat whitespaces and comments to the end of the line. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ while (IS_BLANK(parser->buffer)) {
+ SKIP(parser);
+ if (!CACHE(parser, 1)) goto error;
+ }
+
+ if (CHECK(parser->buffer, '#')) {
+ while (!IS_BREAKZ(parser->buffer)) {
+ SKIP(parser);
+ if (!CACHE(parser, 1)) goto error;
+ }
+ }
+
+ /* Check if we are at the end of the line. */
+
+ if (!IS_BREAKZ(parser->buffer)) {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "did not find expected comment or line break");
+ goto error;
+ }
+
+ /* Eat a line break. */
+
+ if (IS_BREAK(parser->buffer)) {
+ if (!CACHE(parser, 2)) goto error;
+ SKIP_LINE(parser);
+ }
+
+ end_mark = parser->mark;
+
+ /* Set the intendation level if it was specified. */
+
+ if (increment) {
+ indent = parser->indent >= 0 ? parser->indent+increment : increment;
+ }
+
+ /* Scan the leading line breaks and determine the indentation level if needed. */
+
+ if (!yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks,
+ start_mark, &end_mark)) goto error;
+
+ /* Scan the block scalar content. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ while ((int)parser->mark.column == indent && !IS_Z(parser->buffer))
+ {
+ /*
+ * We are at the beginning of a non-empty line.
+ */
+
+ /* Is it a trailing whitespace? */
+
+ trailing_blank = IS_BLANK(parser->buffer);
+
+ /* Check if we need to fold the leading line break. */
+
+ if (!literal && (*leading_break.start == '\n')
+ && !leading_blank && !trailing_blank)
+ {
+ /* Do we need to join the lines by space? */
+
+ if (*trailing_breaks.start == '\0') {
+ if (!STRING_EXTEND(parser, string)) goto error;
+ *(string.pointer ++) = ' ';
+ }
+
+ CLEAR(parser, leading_break);
+ }
+ else {
+ if (!JOIN(parser, string, leading_break)) goto error;
+ CLEAR(parser, leading_break);
+ }
+
+ /* Append the remaining line breaks. */
+
+ if (!JOIN(parser, string, trailing_breaks)) goto error;
+ CLEAR(parser, trailing_breaks);
+
+ /* Is it a leading whitespace? */
+
+ leading_blank = IS_BLANK(parser->buffer);
+
+ /* Consume the current line. */
+
+ while (!IS_BREAKZ(parser->buffer)) {
+ if (!READ(parser, string)) goto error;
+ if (!CACHE(parser, 1)) goto error;
+ }
+
+ /* Consume the line break. */
+
+ if (!CACHE(parser, 2)) goto error;
+
+ if (!READ_LINE(parser, leading_break)) goto error;
+
+ /* Eat the following intendation spaces and line breaks. */
+
+ if (!yaml_parser_scan_block_scalar_breaks(parser,
+ &indent, &trailing_breaks, start_mark, &end_mark)) goto error;
+ }
+
+ /* Chomp the tail. */
+
+ if (chomping != -1) {
+ if (!JOIN(parser, string, leading_break)) goto error;
+ }
+ if (chomping == 1) {
+ if (!JOIN(parser, string, trailing_breaks)) goto error;
+ }
+
+ /* Create a token. */
+
+ SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start,
+ literal ? YAML_LITERAL_SCALAR_STYLE : YAML_FOLDED_SCALAR_STYLE,
+ start_mark, end_mark);
+
+ STRING_DEL(parser, leading_break);
+ STRING_DEL(parser, trailing_breaks);
+
+ return 1;
+
+error:
+ STRING_DEL(parser, string);
+ STRING_DEL(parser, leading_break);
+ STRING_DEL(parser, trailing_breaks);
+
+ return 0;
+}
+
+/*
+ * Scan intendation spaces and line breaks for a block scalar. Determine the
+ * intendation level if needed.
+ */
+
+static int
+yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser,
+ int *indent, yaml_string_t *breaks,
+ yaml_mark_t start_mark, yaml_mark_t *end_mark)
+{
+ int max_indent = 0;
+
+ *end_mark = parser->mark;
+
+ /* Eat the intendation spaces and line breaks. */
+
+ while (1)
+ {
+ /* Eat the intendation spaces. */
+
+ if (!CACHE(parser, 1)) return 0;
+
+ while ((!*indent || (int)parser->mark.column < *indent)
+ && IS_SPACE(parser->buffer)) {
+ SKIP(parser);
+ if (!CACHE(parser, 1)) return 0;
+ }
+
+ if ((int)parser->mark.column > max_indent)
+ max_indent = (int)parser->mark.column;
+
+ /* Check for a tab character messing the intendation. */
+
+ if ((!*indent || (int)parser->mark.column < *indent)
+ && IS_TAB(parser->buffer)) {
+ return yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found a tab character where an intendation space is expected");
+ }
+
+ /* Have we found a non-empty line? */
+
+ if (!IS_BREAK(parser->buffer)) break;
+
+ /* Consume the line break. */
+
+ if (!CACHE(parser, 2)) return 0;
+ if (!READ_LINE(parser, *breaks)) return 0;
+ *end_mark = parser->mark;
+ }
+
+ /* Determine the indentation level if needed. */
+
+ if (!*indent) {
+ *indent = max_indent;
+ if (*indent < parser->indent + 1)
+ *indent = parser->indent + 1;
+ if (*indent < 1)
+ *indent = 1;
+ }
+
+ return 1;
+}
+
+/*
+ * Scan a quoted scalar.
+ */
+
+static int
+yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token,
+ int single)
+{
+ yaml_mark_t start_mark;
+ yaml_mark_t end_mark;
+ yaml_string_t string = NULL_STRING;
+ yaml_string_t leading_break = NULL_STRING;
+ yaml_string_t trailing_breaks = NULL_STRING;
+ yaml_string_t whitespaces = NULL_STRING;
+ int leading_blanks;
+
+ if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
+ if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error;
+ if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error;
+ if (!STRING_INIT(parser, whitespaces, INITIAL_STRING_SIZE)) goto error;
+
+ /* Eat the left quote. */
+
+ start_mark = parser->mark;
+
+ SKIP(parser);
+
+ /* Consume the content of the quoted scalar. */
+
+ while (1)
+ {
+ /* Check that there are no document indicators at the beginning of the line. */
+
+ if (!CACHE(parser, 4)) goto error;
+
+ if (parser->mark.column == 0 &&
+ ((CHECK_AT(parser->buffer, '-', 0) &&
+ CHECK_AT(parser->buffer, '-', 1) &&
+ CHECK_AT(parser->buffer, '-', 2)) ||
+ (CHECK_AT(parser->buffer, '.', 0) &&
+ CHECK_AT(parser->buffer, '.', 1) &&
+ CHECK_AT(parser->buffer, '.', 2))) &&
+ IS_BLANKZ_AT(parser->buffer, 3))
+ {
+ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
+ start_mark, "found unexpected document indicator");
+ goto error;
+ }
+
+ /* Check for EOF. */
+
+ if (IS_Z(parser->buffer)) {
+ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
+ start_mark, "found unexpected end of stream");
+ goto error;
+ }
+
+ /* Consume non-blank characters. */
+
+ if (!CACHE(parser, 2)) goto error;
+
+ leading_blanks = 0;
+
+ while (!IS_BLANKZ(parser->buffer))
+ {
+ /* Check for an escaped single quote. */
+
+ if (single && CHECK_AT(parser->buffer, '\'', 0)
+ && CHECK_AT(parser->buffer, '\'', 1))
+ {
+ if (!STRING_EXTEND(parser, string)) goto error;
+ *(string.pointer++) = '\'';
+ SKIP(parser);
+ SKIP(parser);
+ }
+
+ /* Check for the right quote. */
+
+ else if (CHECK(parser->buffer, single ? '\'' : '"'))
+ {
+ break;
+ }
+
+ /* Check for an escaped line break. */
+
+ else if (!single && CHECK(parser->buffer, '\\')
+ && IS_BREAK_AT(parser->buffer, 1))
+ {
+ if (!CACHE(parser, 3)) goto error;
+ SKIP(parser);
+ SKIP_LINE(parser);
+ leading_blanks = 1;
+ break;
+ }
+
+ /* Check for an escape sequence. */
+
+ else if (!single && CHECK(parser->buffer, '\\'))
+ {
+ size_t code_length = 0;
+
+ if (!STRING_EXTEND(parser, string)) goto error;
+
+ /* Check the escape character. */
+
+ switch (parser->buffer.pointer[1])
+ {
+ case '0':
+ *(string.pointer++) = '\0';
+ break;
+
+ case 'a':
+ *(string.pointer++) = '\x07';
+ break;
+
+ case 'b':
+ *(string.pointer++) = '\x08';
+ break;
+
+ case 't':
+ case '\t':
+ *(string.pointer++) = '\x09';
+ break;
+
+ case 'n':
+ *(string.pointer++) = '\x0A';
+ break;
+
+ case 'v':
+ *(string.pointer++) = '\x0B';
+ break;
+
+ case 'f':
+ *(string.pointer++) = '\x0C';
+ break;
+
+ case 'r':
+ *(string.pointer++) = '\x0D';
+ break;
+
+ case 'e':
+ *(string.pointer++) = '\x1B';
+ break;
+
+ case ' ':
+ *(string.pointer++) = '\x20';
+ break;
+
+ case '"':
+ *(string.pointer++) = '"';
+ break;
+
+ case '\'':
+ *(string.pointer++) = '\'';
+ break;
+
+ case '\\':
+ *(string.pointer++) = '\\';
+ break;
+
+ case 'N': /* NEL (#x85) */
+ *(string.pointer++) = '\xC2';
+ *(string.pointer++) = '\x85';
+ break;
+
+ case '_': /* #xA0 */
+ *(string.pointer++) = '\xC2';
+ *(string.pointer++) = '\xA0';
+ break;
+
+ case 'L': /* LS (#x2028) */
+ *(string.pointer++) = '\xE2';
+ *(string.pointer++) = '\x80';
+ *(string.pointer++) = '\xA8';
+ break;
+
+ case 'P': /* PS (#x2029) */
+ *(string.pointer++) = '\xE2';
+ *(string.pointer++) = '\x80';
+ *(string.pointer++) = '\xA9';
+ break;
+
+ case 'x':
+ code_length = 2;
+ break;
+
+ case 'u':
+ code_length = 4;
+ break;
+
+ case 'U':
+ code_length = 8;
+ break;
+
+ default:
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "found unknown escape character");
+ goto error;
+ }
+
+ SKIP(parser);
+ SKIP(parser);
+
+ /* Consume an arbitrary escape code. */
+
+ if (code_length)
+ {
+ unsigned int value = 0;
+ size_t k;
+
+ /* Scan the character value. */
+
+ if (!CACHE(parser, code_length)) goto error;
+
+ for (k = 0; k < code_length; k ++) {
+ if (!IS_HEX_AT(parser->buffer, k)) {
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "did not find expected hexdecimal number");
+ goto error;
+ }
+ value = (value << 4) + AS_HEX_AT(parser->buffer, k);
+ }
+
+ /* Check the value and write the character. */
+
+ if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "found invalid Unicode character escape code");
+ goto error;
+ }
+
+ if (value <= 0x7F) {
+ *(string.pointer++) = value;
+ }
+ else if (value <= 0x7FF) {
+ *(string.pointer++) = 0xC0 + (value >> 6);
+ *(string.pointer++) = 0x80 + (value & 0x3F);
+ }
+ else if (value <= 0xFFFF) {
+ *(string.pointer++) = 0xE0 + (value >> 12);
+ *(string.pointer++) = 0x80 + ((value >> 6) & 0x3F);
+ *(string.pointer++) = 0x80 + (value & 0x3F);
+ }
+ else {
+ *(string.pointer++) = 0xF0 + (value >> 18);
+ *(string.pointer++) = 0x80 + ((value >> 12) & 0x3F);
+ *(string.pointer++) = 0x80 + ((value >> 6) & 0x3F);
+ *(string.pointer++) = 0x80 + (value & 0x3F);
+ }
+
+ /* Advance the pointer. */
+
+ for (k = 0; k < code_length; k ++) {
+ SKIP(parser);
+ }
+ }
+ }
+
+ else
+ {
+ /* It is a non-escaped non-blank character. */
+
+ if (!READ(parser, string)) goto error;
+ }
+
+ if (!CACHE(parser, 2)) goto error;
+ }
+
+ /* Check if we are at the end of the scalar. */
+
+ if (CHECK(parser->buffer, single ? '\'' : '"'))
+ break;
+
+ /* Consume blank characters. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ while (IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer))
+ {
+ if (IS_BLANK(parser->buffer))
+ {
+ /* Consume a space or a tab character. */
+
+ if (!leading_blanks) {
+ if (!READ(parser, whitespaces)) goto error;
+ }
+ else {
+ SKIP(parser);
+ }
+ }
+ else
+ {
+ if (!CACHE(parser, 2)) goto error;
+
+ /* Check if it is a first line break. */
+
+ if (!leading_blanks)
+ {
+ CLEAR(parser, whitespaces);
+ if (!READ_LINE(parser, leading_break)) goto error;
+ leading_blanks = 1;
+ }
+ else
+ {
+ if (!READ_LINE(parser, trailing_breaks)) goto error;
+ }
+ }
+ if (!CACHE(parser, 1)) goto error;
+ }
+
+ /* Join the whitespaces or fold line breaks. */
+
+ if (leading_blanks)
+ {
+ /* Do we need to fold line breaks? */
+
+ if (leading_break.start[0] == '\n') {
+ if (trailing_breaks.start[0] == '\0') {
+ if (!STRING_EXTEND(parser, string)) goto error;
+ *(string.pointer++) = ' ';
+ }
+ else {
+ if (!JOIN(parser, string, trailing_breaks)) goto error;
+ CLEAR(parser, trailing_breaks);
+ }
+ CLEAR(parser, leading_break);
+ }
+ else {
+ if (!JOIN(parser, string, leading_break)) goto error;
+ if (!JOIN(parser, string, trailing_breaks)) goto error;
+ CLEAR(parser, leading_break);
+ CLEAR(parser, trailing_breaks);
+ }
+ }
+ else
+ {
+ if (!JOIN(parser, string, whitespaces)) goto error;
+ CLEAR(parser, whitespaces);
+ }
+ }
+
+ /* Eat the right quote. */
+
+ SKIP(parser);
+
+ end_mark = parser->mark;
+
+ /* Create a token. */
+
+ SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start,
+ single ? YAML_SINGLE_QUOTED_SCALAR_STYLE : YAML_DOUBLE_QUOTED_SCALAR_STYLE,
+ start_mark, end_mark);
+
+ STRING_DEL(parser, leading_break);
+ STRING_DEL(parser, trailing_breaks);
+ STRING_DEL(parser, whitespaces);
+
+ return 1;
+
+error:
+ STRING_DEL(parser, string);
+ STRING_DEL(parser, leading_break);
+ STRING_DEL(parser, trailing_breaks);
+ STRING_DEL(parser, whitespaces);
+
+ return 0;
+}
+
+/*
+ * Scan a plain scalar.
+ */
+
+static int
+yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token)
+{
+ yaml_mark_t start_mark;
+ yaml_mark_t end_mark;
+ yaml_string_t string = NULL_STRING;
+ yaml_string_t leading_break = NULL_STRING;
+ yaml_string_t trailing_breaks = NULL_STRING;
+ yaml_string_t whitespaces = NULL_STRING;
+ int leading_blanks = 0;
+ int indent = parser->indent+1;
+
+ if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
+ if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error;
+ if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error;
+ if (!STRING_INIT(parser, whitespaces, INITIAL_STRING_SIZE)) goto error;
+
+ start_mark = end_mark = parser->mark;
+
+ /* Consume the content of the plain scalar. */
+
+ while (1)
+ {
+ /* Check for a document indicator. */
+
+ if (!CACHE(parser, 4)) goto error;
+
+ if (parser->mark.column == 0 &&
+ ((CHECK_AT(parser->buffer, '-', 0) &&
+ CHECK_AT(parser->buffer, '-', 1) &&
+ CHECK_AT(parser->buffer, '-', 2)) ||
+ (CHECK_AT(parser->buffer, '.', 0) &&
+ CHECK_AT(parser->buffer, '.', 1) &&
+ CHECK_AT(parser->buffer, '.', 2))) &&
+ IS_BLANKZ_AT(parser->buffer, 3)) break;
+
+ /* Check for a comment. */
+
+ if (CHECK(parser->buffer, '#'))
+ break;
+
+ /* Consume non-blank characters. */
+
+ while (!IS_BLANKZ(parser->buffer))
+ {
+ /* Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13". */
+
+ if (parser->flow_level
+ && CHECK(parser->buffer, ':')
+ && !IS_BLANKZ_AT(parser->buffer, 1)) {
+ yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
+ start_mark, "found unexpected ':'");
+ goto error;
+ }
+
+ /* Check for indicators that may end a plain scalar. */
+
+ if ((CHECK(parser->buffer, ':') && IS_BLANKZ_AT(parser->buffer, 1))
+ || (parser->flow_level &&
+ (CHECK(parser->buffer, ',') || CHECK(parser->buffer, ':')
+ || CHECK(parser->buffer, '?') || CHECK(parser->buffer, '[')
+ || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '{')
+ || CHECK(parser->buffer, '}'))))
+ break;
+
+ /* Check if we need to join whitespaces and breaks. */
+
+ if (leading_blanks || whitespaces.start != whitespaces.pointer)
+ {
+ if (leading_blanks)
+ {
+ /* Do we need to fold line breaks? */
+
+ if (leading_break.start[0] == '\n') {
+ if (trailing_breaks.start[0] == '\0') {
+ if (!STRING_EXTEND(parser, string)) goto error;
+ *(string.pointer++) = ' ';
+ }
+ else {
+ if (!JOIN(parser, string, trailing_breaks)) goto error;
+ CLEAR(parser, trailing_breaks);
+ }
+ CLEAR(parser, leading_break);
+ }
+ else {
+ if (!JOIN(parser, string, leading_break)) goto error;
+ if (!JOIN(parser, string, trailing_breaks)) goto error;
+ CLEAR(parser, leading_break);
+ CLEAR(parser, trailing_breaks);
+ }
+
+ leading_blanks = 0;
+ }
+ else
+ {
+ if (!JOIN(parser, string, whitespaces)) goto error;
+ CLEAR(parser, whitespaces);
+ }
+ }
+
+ /* Copy the character. */
+
+ if (!READ(parser, string)) goto error;
+
+ end_mark = parser->mark;
+
+ if (!CACHE(parser, 2)) goto error;
+ }
+
+ /* Is it the end? */
+
+ if (!(IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer)))
+ break;
+
+ /* Consume blank characters. */
+
+ if (!CACHE(parser, 1)) goto error;
+
+ while (IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer))
+ {
+ if (IS_BLANK(parser->buffer))
+ {
+ /* Check for tab character that abuse intendation. */
+
+ if (leading_blanks && (int)parser->mark.column < indent
+ && IS_TAB(parser->buffer)) {
+ yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
+ start_mark, "found a tab character that violate intendation");
+ goto error;
+ }
+
+ /* Consume a space or a tab character. */
+
+ if (!leading_blanks) {
+ if (!READ(parser, whitespaces)) goto error;
+ }
+ else {
+ SKIP(parser);
+ }
+ }
+ else
+ {
+ if (!CACHE(parser, 2)) goto error;
+
+ /* Check if it is a first line break. */
+
+ if (!leading_blanks)
+ {
+ CLEAR(parser, whitespaces);
+ if (!READ_LINE(parser, leading_break)) goto error;
+ leading_blanks = 1;
+ }
+ else
+ {
+ if (!READ_LINE(parser, trailing_breaks)) goto error;
+ }
+ }
+ if (!CACHE(parser, 1)) goto error;
+ }
+
+ /* Check intendation level. */
+
+ if (!parser->flow_level && (int)parser->mark.column < indent)
+ break;
+ }
+
+ /* Create a token. */
+
+ SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start,
+ YAML_PLAIN_SCALAR_STYLE, start_mark, end_mark);
+
+ /* Note that we change the 'simple_key_allowed' flag. */
+
+ if (leading_blanks) {
+ parser->simple_key_allowed = 1;
+ }
+
+ STRING_DEL(parser, leading_break);
+ STRING_DEL(parser, trailing_breaks);
+ STRING_DEL(parser, whitespaces);
+
+ return 1;
+
+error:
+ STRING_DEL(parser, string);
+ STRING_DEL(parser, leading_break);
+ STRING_DEL(parser, trailing_breaks);
+ STRING_DEL(parser, whitespaces);
+
+ return 0;
+}
+
diff --git a/libyaml/writer.c b/libyaml/writer.c
new file mode 100644
index 0000000..7fc4754
--- /dev/null
+++ b/libyaml/writer.c
@@ -0,0 +1,141 @@
+
+#include "libyaml/yaml_private.h"
+
+/*
+ * Declarations.
+ */
+
+static int
+yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem);
+
+YAML_DECLARE(int)
+yaml_emitter_flush(yaml_emitter_t *emitter);
+
+/*
+ * Set the writer error and return 0.
+ */
+
+static int
+yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem)
+{
+ emitter->error = YAML_WRITER_ERROR;
+ emitter->problem = problem;
+
+ return 0;
+}
+
+/*
+ * Flush the output buffer.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_flush(yaml_emitter_t *emitter)
+{
+ int low, high;
+
+ assert(emitter); /* Non-NULL emitter object is expected. */
+ assert(emitter->write_handler); /* Write handler must be set. */
+ assert(emitter->encoding); /* Output encoding must be set. */
+
+ emitter->buffer.last = emitter->buffer.pointer;
+ emitter->buffer.pointer = emitter->buffer.start;
+
+ /* Check if the buffer is empty. */
+
+ if (emitter->buffer.start == emitter->buffer.last) {
+ return 1;
+ }
+
+ /* If the output encoding is UTF-8, we don't need to recode the buffer. */
+
+ if (emitter->encoding == YAML_UTF8_ENCODING)
+ {
+ if (emitter->write_handler(emitter->write_handler_data,
+ emitter->buffer.start,
+ emitter->buffer.last - emitter->buffer.start)) {
+ emitter->buffer.last = emitter->buffer.start;
+ emitter->buffer.pointer = emitter->buffer.start;
+ return 1;
+ }
+ else {
+ return yaml_emitter_set_writer_error(emitter, "write error");
+ }
+ }
+
+ /* Recode the buffer into the raw buffer. */
+
+ low = (emitter->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
+ high = (emitter->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
+
+ while (emitter->buffer.pointer != emitter->buffer.last)
+ {
+ unsigned char octet;
+ unsigned int width;
+ unsigned int value;
+ size_t k;
+
+ /*
+ * See the "reader.c" code for more details on UTF-8 encoding. Note
+ * that we assume that the buffer contains a valid UTF-8 sequence.
+ */
+
+ /* Read the next UTF-8 character. */
+
+ octet = emitter->buffer.pointer[0];
+
+ width = (octet & 0x80) == 0x00 ? 1 :
+ (octet & 0xE0) == 0xC0 ? 2 :
+ (octet & 0xF0) == 0xE0 ? 3 :
+ (octet & 0xF8) == 0xF0 ? 4 : 0;
+
+ value = (octet & 0x80) == 0x00 ? octet & 0x7F :
+ (octet & 0xE0) == 0xC0 ? octet & 0x1F :
+ (octet & 0xF0) == 0xE0 ? octet & 0x0F :
+ (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
+
+ for (k = 1; k < width; k ++) {
+ octet = emitter->buffer.pointer[k];
+ value = (value << 6) + (octet & 0x3F);
+ }
+
+ emitter->buffer.pointer += width;
+
+ /* Write the character. */
+
+ if (value < 0x10000)
+ {
+ emitter->raw_buffer.last[high] = value >> 8;
+ emitter->raw_buffer.last[low] = value & 0xFF;
+
+ emitter->raw_buffer.last += 2;
+ }
+ else
+ {
+ /* Write the character using a surrogate pair (check "reader.c"). */
+
+ value -= 0x10000;
+ emitter->raw_buffer.last[high] = 0xD8 + (value >> 18);
+ emitter->raw_buffer.last[low] = (value >> 10) & 0xFF;
+ emitter->raw_buffer.last[high+2] = 0xDC + ((value >> 8) & 0xFF);
+ emitter->raw_buffer.last[low+2] = value & 0xFF;
+
+ emitter->raw_buffer.last += 4;
+ }
+ }
+
+ /* Write the raw buffer. */
+
+ if (emitter->write_handler(emitter->write_handler_data,
+ emitter->raw_buffer.start,
+ emitter->raw_buffer.last - emitter->raw_buffer.start)) {
+ emitter->buffer.last = emitter->buffer.start;
+ emitter->buffer.pointer = emitter->buffer.start;
+ emitter->raw_buffer.last = emitter->raw_buffer.start;
+ emitter->raw_buffer.pointer = emitter->raw_buffer.start;
+ return 1;
+ }
+ else {
+ return yaml_emitter_set_writer_error(emitter, "write error");
+ }
+}
+
diff --git a/libyaml/yaml.h b/libyaml/yaml.h
new file mode 100644
index 0000000..e4e73bf
--- /dev/null
+++ b/libyaml/yaml.h
@@ -0,0 +1,1962 @@
+/**
+ * @file yaml_api.h
+ * @brief Public interface for libyaml.
+ *
+ * Include the header file with the code:
+ * @code
+ * #include
+ * @endcode
+ */
+
+#ifndef YAML_H
+#define YAML_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+
+/**
+ * @defgroup export Export Definitions
+ * @{
+ */
+
+/** The public API declaration. */
+
+
+# define YAML_DECLARE(type) type
+
+/** @} */
+
+/**
+ * @defgroup titleVersion titleVersion Information
+ * @{
+ */
+
+/**
+ * Get the library titleVersion as a string.
+ *
+ * @returns The function returns the pointer to a static string of the form
+ * @c "X.Y.Z", where @c X is the major titleVersion number, @c Y is a minor titleVersion
+ * number, and @c Z is the patch titleVersion number.
+ */
+
+YAML_DECLARE(const char *)
+yaml_get_titleVersion_string(void);
+
+/**
+ * Get the library titleVersion numbers.
+ *
+ * @param[out] major Major titleVersion number.
+ * @param[out] minor Minor titleVersion number.
+ * @param[out] patch Patch titleVersion number.
+ */
+
+YAML_DECLARE(void)
+yaml_get_titleVersion(int *major, int *minor, int *patch);
+
+/** @} */
+
+/**
+ * @defgroup basic Basic Types
+ * @{
+ */
+
+/** The character type (UTF-8 octet). */
+typedef unsigned char yaml_char_t;
+
+/** The titleVersion directive data. */
+typedef struct yaml_titleVersion_directive_s {
+ /** The major titleVersion number. */
+ int major;
+ /** The minor titleVersion number. */
+ int minor;
+} yaml_titleVersion_directive_t;
+
+/** The tag directive data. */
+typedef struct yaml_tag_directive_s {
+ /** The tag handle. */
+ yaml_char_t *handle;
+ /** The tag prefix. */
+ yaml_char_t *prefix;
+} yaml_tag_directive_t;
+
+/** The stream encoding. */
+typedef enum yaml_encoding_e {
+ /** Let the parser choose the encoding. */
+ YAML_ANY_ENCODING,
+ /** The default UTF-8 encoding. */
+ YAML_UTF8_ENCODING,
+ /** The UTF-16-LE encoding with BOM. */
+ YAML_UTF16LE_ENCODING,
+ /** The UTF-16-BE encoding with BOM. */
+ YAML_UTF16BE_ENCODING
+} yaml_encoding_t;
+
+/** Line break types. */
+
+typedef enum yaml_break_e {
+ /** Let the parser choose the break type. */
+ YAML_ANY_BREAK,
+ /** Use CR for line breaks (Mac style). */
+ YAML_CR_BREAK,
+ /** Use LN for line breaks (Unix style). */
+ YAML_LN_BREAK,
+ /** Use CR LN for line breaks (DOS style). */
+ YAML_CRLN_BREAK
+} yaml_break_t;
+
+/** Many bad things could happen with the parser and emitter. */
+typedef enum yaml_error_type_e {
+ /** No error is produced. */
+ YAML_NO_ERROR,
+
+ /** Cannot allocate or reallocate a block of memory. */
+ YAML_MEMORY_ERROR,
+
+ /** Cannot read or decode the input stream. */
+ YAML_READER_ERROR,
+ /** Cannot scan the input stream. */
+ YAML_SCANNER_ERROR,
+ /** Cannot parse the input stream. */
+ YAML_PARSER_ERROR,
+ /** Cannot compose a YAML document. */
+ YAML_COMPOSER_ERROR,
+
+ /** Cannot write to the output stream. */
+ YAML_WRITER_ERROR,
+ /** Cannot emit a YAML stream. */
+ YAML_EMITTER_ERROR
+} yaml_error_type_t;
+
+/** The pointer position. */
+typedef struct yaml_mark_s {
+ /** The position index. */
+ size_t index;
+
+ /** The position line. */
+ size_t line;
+
+ /** The position column. */
+ size_t column;
+} yaml_mark_t;
+
+/** @} */
+
+/**
+ * @defgroup styles Node Styles
+ * @{
+ */
+
+/** Scalar styles. */
+typedef enum yaml_scalar_style_e {
+ /** Let the emitter choose the style. */
+ YAML_ANY_SCALAR_STYLE,
+
+ /** The plain scalar style. */
+ YAML_PLAIN_SCALAR_STYLE,
+
+ /** The single-quoted scalar style. */
+ YAML_SINGLE_QUOTED_SCALAR_STYLE,
+ /** The double-quoted scalar style. */
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE,
+
+ /** The literal scalar style. */
+ YAML_LITERAL_SCALAR_STYLE,
+ /** The folded scalar style. */
+ YAML_FOLDED_SCALAR_STYLE
+} yaml_scalar_style_t;
+
+/** Sequence styles. */
+typedef enum yaml_sequence_style_e {
+ /** Let the emitter choose the style. */
+ YAML_ANY_SEQUENCE_STYLE,
+
+ /** The block sequence style. */
+ YAML_BLOCK_SEQUENCE_STYLE,
+ /** The flow sequence style. */
+ YAML_FLOW_SEQUENCE_STYLE
+} yaml_sequence_style_t;
+
+/** Mapping styles. */
+typedef enum yaml_mapping_style_e {
+ /** Let the emitter choose the style. */
+ YAML_ANY_MAPPING_STYLE,
+
+ /** The block mapping style. */
+ YAML_BLOCK_MAPPING_STYLE,
+ /** The flow mapping style. */
+ YAML_FLOW_MAPPING_STYLE
+/* YAML_FLOW_SET_MAPPING_STYLE */
+} yaml_mapping_style_t;
+
+/** @} */
+
+/**
+ * @defgroup tokens Tokens
+ * @{
+ */
+
+/** Token types. */
+typedef enum yaml_token_type_e {
+ /** An empty token. */
+ YAML_NO_TOKEN,
+
+ /** A STREAM-START token. */
+ YAML_STREAM_START_TOKEN,
+ /** A STREAM-END token. */
+ YAML_STREAM_END_TOKEN,
+
+ /** A titleVersion-DIRECTIVE token. */
+ YAML_titleVersion_DIRECTIVE_TOKEN,
+ /** A TAG-DIRECTIVE token. */
+ YAML_TAG_DIRECTIVE_TOKEN,
+ /** A DOCUMENT-START token. */
+ YAML_DOCUMENT_START_TOKEN,
+ /** A DOCUMENT-END token. */
+ YAML_DOCUMENT_END_TOKEN,
+
+ /** A BLOCK-SEQUENCE-START token. */
+ YAML_BLOCK_SEQUENCE_START_TOKEN,
+ /** A BLOCK-SEQUENCE-END token. */
+ YAML_BLOCK_MAPPING_START_TOKEN,
+ /** A BLOCK-END token. */
+ YAML_BLOCK_END_TOKEN,
+
+ /** A FLOW-SEQUENCE-START token. */
+ YAML_FLOW_SEQUENCE_START_TOKEN,
+ /** A FLOW-SEQUENCE-END token. */
+ YAML_FLOW_SEQUENCE_END_TOKEN,
+ /** A FLOW-MAPPING-START token. */
+ YAML_FLOW_MAPPING_START_TOKEN,
+ /** A FLOW-MAPPING-END token. */
+ YAML_FLOW_MAPPING_END_TOKEN,
+
+ /** A BLOCK-ENTRY token. */
+ YAML_BLOCK_ENTRY_TOKEN,
+ /** A FLOW-ENTRY token. */
+ YAML_FLOW_ENTRY_TOKEN,
+ /** A KEY token. */
+ YAML_KEY_TOKEN,
+ /** A VALUE token. */
+ YAML_VALUE_TOKEN,
+
+ /** An ALIAS token. */
+ YAML_ALIAS_TOKEN,
+ /** An ANCHOR token. */
+ YAML_ANCHOR_TOKEN,
+ /** A TAG token. */
+ YAML_TAG_TOKEN,
+ /** A SCALAR token. */
+ YAML_SCALAR_TOKEN
+} yaml_token_type_t;
+
+/** The token structure. */
+typedef struct yaml_token_s {
+
+ /** The token type. */
+ yaml_token_type_t type;
+
+ /** The token data. */
+ union {
+
+ /** The stream start (for @c YAML_STREAM_START_TOKEN). */
+ struct {
+ /** The stream encoding. */
+ yaml_encoding_t encoding;
+ } stream_start;
+
+ /** The alias (for @c YAML_ALIAS_TOKEN). */
+ struct {
+ /** The alias value. */
+ yaml_char_t *value;
+ } alias;
+
+ /** The anchor (for @c YAML_ANCHOR_TOKEN). */
+ struct {
+ /** The anchor value. */
+ yaml_char_t *value;
+ } anchor;
+
+ /** The tag (for @c YAML_TAG_TOKEN). */
+ struct {
+ /** The tag handle. */
+ yaml_char_t *handle;
+ /** The tag suffix. */
+ yaml_char_t *suffix;
+ } tag;
+
+ /** The scalar value (for @c YAML_SCALAR_TOKEN). */
+ struct {
+ /** The scalar value. */
+ yaml_char_t *value;
+ /** The length of the scalar value. */
+ size_t length;
+ /** The scalar style. */
+ yaml_scalar_style_t style;
+ } scalar;
+
+ /** The titleVersion directive (for @c YAML_titleVersion_DIRECTIVE_TOKEN). */
+ struct {
+ /** The major titleVersion number. */
+ int major;
+ /** The minor titleVersion number. */
+ int minor;
+ } titleVersion_directive;
+
+ /** The tag directive (for @c YAML_TAG_DIRECTIVE_TOKEN). */
+ struct {
+ /** The tag handle. */
+ yaml_char_t *handle;
+ /** The tag prefix. */
+ yaml_char_t *prefix;
+ } tag_directive;
+
+ } data;
+
+ /** The beginning of the token. */
+ yaml_mark_t start_mark;
+ /** The end of the token. */
+ yaml_mark_t end_mark;
+
+} yaml_token_t;
+
+/**
+ * Free any memory allocated for a token object.
+ *
+ * @param[in,out] token A token object.
+ */
+
+YAML_DECLARE(void)
+yaml_token_delete(yaml_token_t *token);
+
+/** @} */
+
+/**
+ * @defgroup events Events
+ * @{
+ */
+
+/** Event types. */
+typedef enum yaml_event_type_e {
+ /** An empty event. */
+ YAML_NO_EVENT, // 0
+
+ /** A STREAM-START event. */
+ YAML_STREAM_START_EVENT, // 1
+ /** A STREAM-END event. */
+ YAML_STREAM_END_EVENT, // 2
+
+ /** A DOCUMENT-START event. */
+ YAML_DOCUMENT_START_EVENT, // 3
+ /** A DOCUMENT-END event. */
+ YAML_DOCUMENT_END_EVENT, // 4
+
+ /** An ALIAS event. */
+ YAML_ALIAS_EVENT, // 5
+ /** A SCALAR event. */
+ YAML_SCALAR_EVENT, // 6
+
+ /** A SEQUENCE-START event. */
+ YAML_SEQUENCE_START_EVENT, // 7
+ /** A SEQUENCE-END event. */
+ YAML_SEQUENCE_END_EVENT, // 8
+
+ /** A MAPPING-START event. */
+ YAML_MAPPING_START_EVENT, // 9
+ /** A MAPPING-END event. */
+ YAML_MAPPING_END_EVENT // 10
+} yaml_event_type_t;
+
+/** The event structure. */
+typedef struct yaml_event_s {
+
+ /** The event type. */
+ yaml_event_type_t type;
+
+ /** The event data. */
+ union {
+
+ /** The stream parameters (for @c YAML_STREAM_START_EVENT). */ // 1
+ struct {
+ /** The document encoding. */
+ yaml_encoding_t encoding;
+ } stream_start;
+
+ /** The document parameters (for @c YAML_DOCUMENT_START_EVENT). */ // 3
+ struct {
+ /** The titleVersion directive. */
+ yaml_titleVersion_directive_t *titleVersion_directive;
+
+ /** The list of tag directives. */
+ struct {
+ /** The beginning of the tag directives list. */
+ yaml_tag_directive_t *start;
+ /** The end of the tag directives list. */
+ yaml_tag_directive_t *end;
+ } tag_directives;
+
+ /** Is the document indicator implicit? */
+ int implicit;
+ } document_start;
+
+ /** The document end parameters (for @c YAML_DOCUMENT_END_EVENT). */ // 4
+ struct {
+ /** Is the document end indicator implicit? */
+ int implicit;
+ } document_end;
+
+ /** The alias parameters (for @c YAML_ALIAS_EVENT). */ // 5
+ struct {
+ /** The anchor. */
+ yaml_char_t *anchor;
+ } alias;
+
+ /** The scalar parameters (for @c YAML_SCALAR_EVENT). */ // 6
+ struct {
+ /** The anchor. */
+ yaml_char_t *anchor;
+ /** The tag. */
+ yaml_char_t *tag;
+ /** The scalar value. */
+ yaml_char_t *value;
+ /** The length of the scalar value. */
+ size_t length;
+ /** Is the tag optional for the plain style? */
+ int plain_implicit;
+ /** Is the tag optional for any non-plain style? */
+ int quoted_implicit;
+ /** The scalar style. */
+ yaml_scalar_style_t style;
+ } scalar;
+
+ /** The sequence parameters (for @c YAML_SEQUENCE_START_EVENT). */ // 7
+ struct {
+ /** The anchor. */
+ yaml_char_t *anchor;
+ /** The tag. */
+ yaml_char_t *tag;
+ /** Is the tag optional? */
+ int implicit;
+ /** The sequence style. */
+ yaml_sequence_style_t style;
+ } sequence_start;
+
+ /** The mapping parameters (for @c YAML_MAPPING_START_EVENT). */ // 9
+ struct {
+ /** The anchor. */
+ yaml_char_t *anchor;
+ /** The tag. */
+ yaml_char_t *tag;
+ /** Is the tag optional? */
+ int implicit;
+ /** The mapping style. */
+ yaml_mapping_style_t style;
+ } mapping_start;
+
+ } data;
+
+ /** The beginning of the event. */
+ yaml_mark_t start_mark;
+ /** The end of the event. */
+ yaml_mark_t end_mark;
+
+} yaml_event_t;
+
+/**
+ * Create the STREAM-START event.
+ *
+ * @param[out] event An empty event object.
+ * @param[in] encoding The stream encoding.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_stream_start_event_initialize(yaml_event_t *event,
+ yaml_encoding_t encoding);
+
+/**
+ * Create the STREAM-END event.
+ *
+ * @param[out] event An empty event object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_stream_end_event_initialize(yaml_event_t *event);
+
+/**
+ * Create the DOCUMENT-START event.
+ *
+ * The @a implicit argument is considered as a stylistic parameter and may be
+ * ignored by the emitter.
+ *
+ * @param[out] event An empty event object.
+ * @param[in] titleVersion_directive The %YAML directive value or
+ * @c NULL.
+ * @param[in] tag_directives_start The beginning of the %TAG
+ * directives list.
+ * @param[in] tag_directives_end The end of the %TAG directives
+ * list.
+ * @param[in] implicit If the document start indicator is
+ * implicit.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_document_start_event_initialize(yaml_event_t *event,
+ yaml_titleVersion_directive_t *titleVersion_directive,
+ yaml_tag_directive_t *tag_directives_start,
+ yaml_tag_directive_t *tag_directives_end,
+ int implicit);
+
+/**
+ * Create the DOCUMENT-END event.
+ *
+ * The @a implicit argument is considered as a stylistic parameter and may be
+ * ignored by the emitter.
+ *
+ * @param[out] event An empty event object.
+ * @param[in] implicit If the document end indicator is implicit.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_document_end_event_initialize(yaml_event_t *event, int implicit);
+
+/**
+ * Create an ALIAS event.
+ *
+ * @param[out] event An empty event object.
+ * @param[in] anchor The anchor value.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor);
+
+/**
+ * Create a SCALAR event.
+ *
+ * The @a style argument may be ignored by the emitter.
+ *
+ * Either the @a tag attribute or one of the @a plain_implicit and
+ * @a quoted_implicit flags must be set.
+ *
+ * @param[out] event An empty event object.
+ * @param[in] anchor The scalar anchor or @c NULL.
+ * @param[in] tag The scalar tag or @c NULL.
+ * @param[in] value The scalar value.
+ * @param[in] length The length of the scalar value.
+ * @param[in] plain_implicit If the tag may be omitted for the plain
+ * style.
+ * @param[in] quoted_implicit If the tag may be omitted for any
+ * non-plain style.
+ * @param[in] style The scalar style.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_scalar_event_initialize(yaml_event_t *event,
+ yaml_char_t *anchor, yaml_char_t *tag,
+ yaml_char_t *value, int length,
+ int plain_implicit, int quoted_implicit,
+ yaml_scalar_style_t style);
+
+/**
+ * Create a SEQUENCE-START event.
+ *
+ * The @a style argument may be ignored by the emitter.
+ *
+ * Either the @a tag attribute or the @a implicit flag must be set.
+ *
+ * @param[out] event An empty event object.
+ * @param[in] anchor The sequence anchor or @c NULL.
+ * @param[in] tag The sequence tag or @c NULL.
+ * @param[in] implicit If the tag may be omitted.
+ * @param[in] style The sequence style.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_sequence_start_event_initialize(yaml_event_t *event,
+ yaml_char_t *anchor, yaml_char_t *tag, int implicit,
+ yaml_sequence_style_t style);
+
+/**
+ * Create a SEQUENCE-END event.
+ *
+ * @param[out] event An empty event object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_sequence_end_event_initialize(yaml_event_t *event);
+
+/**
+ * Create a MAPPING-START event.
+ *
+ * The @a style argument may be ignored by the emitter.
+ *
+ * Either the @a tag attribute or the @a implicit flag must be set.
+ *
+ * @param[out] event An empty event object.
+ * @param[in] anchor The mapping anchor or @c NULL.
+ * @param[in] tag The mapping tag or @c NULL.
+ * @param[in] implicit If the tag may be omitted.
+ * @param[in] style The mapping style.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_mapping_start_event_initialize(yaml_event_t *event,
+ yaml_char_t *anchor, yaml_char_t *tag, int implicit,
+ yaml_mapping_style_t style);
+
+/**
+ * Create a MAPPING-END event.
+ *
+ * @param[out] event An empty event object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_mapping_end_event_initialize(yaml_event_t *event);
+
+/**
+ * Free any memory allocated for an event object.
+ *
+ * @param[in,out] event An event object.
+ */
+
+YAML_DECLARE(void)
+yaml_event_delete(yaml_event_t *event);
+
+/** @} */
+
+/**
+ * @defgroup nodes Nodes
+ * @{
+ */
+
+/** The tag @c !!null with the only possible value: @c null. */
+#define YAML_NULL_TAG "tag:yaml.org,2002:null"
+/** The tag @c !!bool with the values: @c true and @c falce. */
+#define YAML_BOOL_TAG "tag:yaml.org,2002:bool"
+/** The tag @c !!str for string values. */
+#define YAML_STR_TAG "tag:yaml.org,2002:str"
+/** The tag @c !!int for integer values. */
+#define YAML_INT_TAG "tag:yaml.org,2002:int"
+/** The tag @c !!float for float values. */
+#define YAML_FLOAT_TAG "tag:yaml.org,2002:float"
+/** The tag @c !!timestamp for date and time values. */
+#define YAML_TIMESTAMP_TAG "tag:yaml.org,2002:timestamp"
+
+/** The tag @c !!seq is used to denote sequences. */
+#define YAML_SEQ_TAG "tag:yaml.org,2002:seq"
+/** The tag @c !!map is used to denote mapping. */
+#define YAML_MAP_TAG "tag:yaml.org,2002:map"
+
+/** The default scalar tag is @c !!str. */
+#define YAML_DEFAULT_SCALAR_TAG YAML_STR_TAG
+/** The default sequence tag is @c !!seq. */
+#define YAML_DEFAULT_SEQUENCE_TAG YAML_SEQ_TAG
+/** The default mapping tag is @c !!map. */
+#define YAML_DEFAULT_MAPPING_TAG YAML_MAP_TAG
+
+/** Node types. */
+typedef enum yaml_node_type_e {
+ /** An empty node. */
+ YAML_NO_NODE,
+
+ /** A scalar node. */
+ YAML_SCALAR_NODE,
+ /** A sequence node. */
+ YAML_SEQUENCE_NODE,
+ /** A mapping node. */
+ YAML_MAPPING_NODE
+} yaml_node_type_t;
+
+/** The forward definition of a document node structure. */
+typedef struct yaml_node_s yaml_node_t;
+
+/** An element of a sequence node. */
+typedef int yaml_node_item_t;
+
+/** An element of a mapping node. */
+typedef struct yaml_node_pair_s {
+ /** The key of the element. */
+ int key;
+ /** The value of the element. */
+ int value;
+} yaml_node_pair_t;
+
+/** The node structure. */
+struct yaml_node_s {
+
+ /** The node type. */
+ yaml_node_type_t type;
+
+ /** The node tag. */
+ yaml_char_t *tag;
+
+ /** The node data. */
+ union {
+
+ /** The scalar parameters (for @c YAML_SCALAR_NODE). */
+ struct {
+ /** The scalar value. */
+ yaml_char_t *value;
+ /** The length of the scalar value. */
+ size_t length;
+ /** The scalar style. */
+ yaml_scalar_style_t style;
+ } scalar;
+
+ /** The sequence parameters (for @c YAML_SEQUENCE_NODE). */
+ struct {
+ /** The stack of sequence items. */
+ struct {
+ /** The beginning of the stack. */
+ yaml_node_item_t *start;
+ /** The end of the stack. */
+ yaml_node_item_t *end;
+ /** The top of the stack. */
+ yaml_node_item_t *top;
+ } items;
+ /** The sequence style. */
+ yaml_sequence_style_t style;
+ } sequence;
+
+ /** The mapping parameters (for @c YAML_MAPPING_NODE). */
+ struct {
+ /** The stack of mapping pairs (key, value). */
+ struct {
+ /** The beginning of the stack. */
+ yaml_node_pair_t *start;
+ /** The end of the stack. */
+ yaml_node_pair_t *end;
+ /** The top of the stack. */
+ yaml_node_pair_t *top;
+ } pairs;
+ /** The mapping style. */
+ yaml_mapping_style_t style;
+ } mapping;
+
+ } data;
+
+ /** The beginning of the node. */
+ yaml_mark_t start_mark;
+ /** The end of the node. */
+ yaml_mark_t end_mark;
+
+};
+
+/** The document structure. */
+typedef struct yaml_document_s {
+
+ /** The document nodes. */
+ struct {
+ /** The beginning of the stack. */
+ yaml_node_t *start;
+ /** The end of the stack. */
+ yaml_node_t *end;
+ /** The top of the stack. */
+ yaml_node_t *top;
+ } nodes;
+
+ /** The titleVersion directive. */
+ yaml_titleVersion_directive_t *titleVersion_directive;
+
+ /** The list of tag directives. */
+ struct {
+ /** The beginning of the tag directives list. */
+ yaml_tag_directive_t *start;
+ /** The end of the tag directives list. */
+ yaml_tag_directive_t *end;
+ } tag_directives;
+
+ /** Is the document start indicator implicit? */
+ int start_implicit;
+ /** Is the document end indicator implicit? */
+ int end_implicit;
+
+ /** The beginning of the document. */
+ yaml_mark_t start_mark;
+ /** The end of the document. */
+ yaml_mark_t end_mark;
+
+} yaml_document_t;
+
+/**
+ * Create a YAML document.
+ *
+ * @param[out] document An empty document object.
+ * @param[in] titleVersion_directive The %YAML directive value or
+ * @c NULL.
+ * @param[in] tag_directives_start The beginning of the %TAG
+ * directives list.
+ * @param[in] tag_directives_end The end of the %TAG directives
+ * list.
+ * @param[in] start_implicit If the document start indicator is
+ * implicit.
+ * @param[in] end_implicit If the document end indicator is
+ * implicit.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_document_initialize(yaml_document_t *document,
+ yaml_titleVersion_directive_t *titleVersion_directive,
+ yaml_tag_directive_t *tag_directives_start,
+ yaml_tag_directive_t *tag_directives_end,
+ int start_implicit, int end_implicit);
+
+/**
+ * Delete a YAML document and all its nodes.
+ *
+ * @param[in,out] document A document object.
+ */
+
+YAML_DECLARE(void)
+yaml_document_delete(yaml_document_t *document);
+
+/**
+ * Get a node of a YAML document.
+ *
+ * The pointer returned by this function is valid until any of the functions
+ * modifying the documents are called.
+ *
+ * @param[in] document A document object.
+ * @param[in] index The node id.
+ *
+ * @returns the node objct or @c NULL if @c node_id is out of range.
+ */
+
+YAML_DECLARE(yaml_node_t *)
+yaml_document_get_node(yaml_document_t *document, int index);
+
+/**
+ * Get the root of a YAML document node.
+ *
+ * The root object is the first object added to the document.
+ *
+ * The pointer returned by this function is valid until any of the functions
+ * modifying the documents are called.
+ *
+ * An empty document produced by the parser signifies the end of a YAML
+ * stream.
+ *
+ * @param[in] document A document object.
+ *
+ * @returns the node object or @c NULL if the document is empty.
+ */
+
+YAML_DECLARE(yaml_node_t *)
+yaml_document_get_root_node(yaml_document_t *document);
+
+/**
+ * Create a SCALAR node and attach it to the document.
+ *
+ * The @a style argument may be ignored by the emitter.
+ *
+ * @param[in,out] document A document object.
+ * @param[in] tag The scalar tag.
+ * @param[in] value The scalar value.
+ * @param[in] length The length of the scalar value.
+ * @param[in] style The scalar style.
+ *
+ * @returns the node id or @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_scalar(yaml_document_t *document,
+ yaml_char_t *tag, yaml_char_t *value, int length,
+ yaml_scalar_style_t style);
+
+/**
+ * Create a SEQUENCE node and attach it to the document.
+ *
+ * The @a style argument may be ignored by the emitter.
+ *
+ * @param[in,out] document A document object.
+ * @param[in] tag The sequence tag.
+ * @param[in] style The sequence style.
+ *
+ * @returns the node id or @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_sequence(yaml_document_t *document,
+ yaml_char_t *tag, yaml_sequence_style_t style);
+
+/**
+ * Create a MAPPING node and attach it to the document.
+ *
+ * The @a style argument may be ignored by the emitter.
+ *
+ * @param[in,out] document A document object.
+ * @param[in] tag The sequence tag.
+ * @param[in] style The sequence style.
+ *
+ * @returns the node id or @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_document_add_mapping(yaml_document_t *document,
+ yaml_char_t *tag, yaml_mapping_style_t style);
+
+/**
+ * Add an item to a SEQUENCE node.
+ *
+ * @param[in,out] document A document object.
+ * @param[in] sequence The sequence node id.
+ * @param[in] item The item node id.
+*
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_document_append_sequence_item(yaml_document_t *document,
+ int sequence, int item);
+
+/**
+ * Add a pair of a key and a value to a MAPPING node.
+ *
+ * @param[in,out] document A document object.
+ * @param[in] mapping The mapping node id.
+ * @param[in] key The key node id.
+ * @param[in] value The value node id.
+*
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_document_append_mapping_pair(yaml_document_t *document,
+ int mapping, int key, int value);
+
+/** @} */
+
+/**
+ * @defgroup parser Parser Definitions
+ * @{
+ */
+
+/**
+ * The prototype of a read handler.
+ *
+ * The read handler is called when the parser needs to read more bytes from the
+ * source. The handler should write not more than @a size bytes to the @a
+ * buffer. The number of written bytes should be set to the @a length variable.
+ *
+ * @param[in,out] data A pointer to an application data specified by
+ * yaml_parser_set_input().
+ * @param[out] buffer The buffer to write the data from the source.
+ * @param[in] size The size of the buffer.
+ * @param[out] size_read The actual number of bytes read from the source.
+ *
+ * @returns On success, the handler should return @c 1. If the handler failed,
+ * the returned value should be @c 0. On EOF, the handler should set the
+ * @a size_read to @c 0 and return @c 1.
+ */
+
+typedef int yaml_read_handler_t(void *data, unsigned char *buffer, size_t size,
+ size_t *size_read);
+
+/**
+ * This structure holds information about a potential simple key.
+ */
+
+typedef struct yaml_simple_key_s {
+ /** Is a simple key possible? */
+ int possible;
+
+ /** Is a simple key required? */
+ int required;
+
+ /** The number of the token. */
+ size_t token_number;
+
+ /** The position mark. */
+ yaml_mark_t mark;
+} yaml_simple_key_t;
+
+/**
+ * The states of the parser.
+ */
+typedef enum yaml_parser_state_e {
+ /** Expect STREAM-START. */
+ YAML_PARSE_STREAM_START_STATE,
+ /** Expect the beginning of an implicit document. */
+ YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE,
+ /** Expect DOCUMENT-START. */
+ YAML_PARSE_DOCUMENT_START_STATE,
+ /** Expect the content of a document. */
+ YAML_PARSE_DOCUMENT_CONTENT_STATE,
+ /** Expect DOCUMENT-END. */
+ YAML_PARSE_DOCUMENT_END_STATE,
+ /** Expect a block node. */
+ YAML_PARSE_BLOCK_NODE_STATE,
+ /** Expect a block node or indentless sequence. */
+ YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE,
+ /** Expect a flow node. */
+ YAML_PARSE_FLOW_NODE_STATE,
+ /** Expect the first entry of a block sequence. */
+ YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE,
+ /** Expect an entry of a block sequence. */
+ YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE,
+ /** Expect an entry of an indentless sequence. */
+ YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE,
+ /** Expect the first key of a block mapping. */
+ YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE,
+ /** Expect a block mapping key. */
+ YAML_PARSE_BLOCK_MAPPING_KEY_STATE,
+ /** Expect a block mapping value. */
+ YAML_PARSE_BLOCK_MAPPING_VALUE_STATE,
+ /** Expect the first entry of a flow sequence. */
+ YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE,
+ /** Expect an entry of a flow sequence. */
+ YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE,
+ /** Expect a key of an ordered mapping. */
+ YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE,
+ /** Expect a value of an ordered mapping. */
+ YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE,
+ /** Expect the and of an ordered mapping entry. */
+ YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE,
+ /** Expect the first key of a flow mapping. */
+ YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE,
+ /** Expect a key of a flow mapping. */
+ YAML_PARSE_FLOW_MAPPING_KEY_STATE,
+ /** Expect a value of a flow mapping. */
+ YAML_PARSE_FLOW_MAPPING_VALUE_STATE,
+ /** Expect an empty value of a flow mapping. */
+ YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE,
+ /** Expect nothing. */
+ YAML_PARSE_END_STATE
+} yaml_parser_state_t;
+
+/**
+ * This structure holds aliases data.
+ */
+
+typedef struct yaml_alias_data_s {
+ /** The anchor. */
+ yaml_char_t *anchor;
+ /** The node id. */
+ int index;
+ /** The anchor mark. */
+ yaml_mark_t mark;
+} yaml_alias_data_t;
+
+/**
+ * The parser structure.
+ *
+ * All members are internal. Manage the structure using the @c yaml_parser_
+ * family of functions.
+ */
+
+typedef struct yaml_parser_s {
+
+ /**
+ * @name Error handling
+ * @{
+ */
+
+ /** Error type. */
+ yaml_error_type_t error;
+ /** Error description. */
+ const char *problem;
+ /** The byte about which the problem occured. */
+ size_t problem_offset;
+ /** The problematic value (@c -1 is none). */
+ int problem_value;
+ /** The problem position. */
+ yaml_mark_t problem_mark;
+ /** The error context. */
+ const char *context;
+ /** The context position. */
+ yaml_mark_t context_mark;
+
+ /**
+ * @}
+ */
+
+ /**
+ * @name Reader stuff
+ * @{
+ */
+
+ /** Read handler. */
+ yaml_read_handler_t *read_handler;
+
+ /** A pointer for passing to the read handler. */
+ void *read_handler_data;
+
+ /** Standard (string or file) input data. */
+ union {
+ /** String input data. */
+ struct {
+ /** The string start pointer. */
+ const unsigned char *start;
+ /** The string end pointer. */
+ const unsigned char *end;
+ /** The string current position. */
+ const unsigned char *current;
+ } string;
+
+ /** File input data. */
+ FILE *file;
+ } input;
+
+ /** EOF flag */
+ int eof;
+
+ /** The working buffer. */
+ struct {
+ /** The beginning of the buffer. */
+ yaml_char_t *start;
+ /** The end of the buffer. */
+ yaml_char_t *end;
+ /** The current position of the buffer. */
+ yaml_char_t *pointer;
+ /** The last filled position of the buffer. */
+ yaml_char_t *last;
+ } buffer;
+
+ /* The number of unread characters in the buffer. */
+ size_t unread;
+
+ /** The raw buffer. */
+ struct {
+ /** The beginning of the buffer. */
+ unsigned char *start;
+ /** The end of the buffer. */
+ unsigned char *end;
+ /** The current position of the buffer. */
+ unsigned char *pointer;
+ /** The last filled position of the buffer. */
+ unsigned char *last;
+ } raw_buffer;
+
+ /** The input encoding. */
+ yaml_encoding_t encoding;
+
+ /** The offset of the current position (in bytes). */
+ size_t offset;
+
+ /** The mark of the current position. */
+ yaml_mark_t mark;
+
+ /**
+ * @}
+ */
+
+ /**
+ * @name Scanner stuff
+ * @{
+ */
+
+ /** Have we started to scan the input stream? */
+ int stream_start_produced;
+
+ /** Have we reached the end of the input stream? */
+ int stream_end_produced;
+
+ /** The number of unclosed '[' and '{' indicators. */
+ int flow_level;
+
+ /** The tokens queue. */
+ struct {
+ /** The beginning of the tokens queue. */
+ yaml_token_t *start;
+ /** The end of the tokens queue. */
+ yaml_token_t *end;
+ /** The head of the tokens queue. */
+ yaml_token_t *head;
+ /** The tail of the tokens queue. */
+ yaml_token_t *tail;
+ } tokens;
+
+ /** The number of tokens fetched from the queue. */
+ size_t tokens_parsed;
+
+ /* Does the tokens queue contain a token ready for dequeueing. */
+ int token_available;
+
+ /** The indentation levels stack. */
+ struct {
+ /** The beginning of the stack. */
+ int *start;
+ /** The end of the stack. */
+ int *end;
+ /** The top of the stack. */
+ int *top;
+ } indents;
+
+ /** The current indentation level. */
+ int indent;
+
+ /** May a simple key occur at the current position? */
+ int simple_key_allowed;
+
+ /** The stack of simple keys. */
+ struct {
+ /** The beginning of the stack. */
+ yaml_simple_key_t *start;
+ /** The end of the stack. */
+ yaml_simple_key_t *end;
+ /** The top of the stack. */
+ yaml_simple_key_t *top;
+ } simple_keys;
+
+ /**
+ * @}
+ */
+
+ /**
+ * @name Parser stuff
+ * @{
+ */
+
+ /** The parser states stack. */
+ struct {
+ /** The beginning of the stack. */
+ yaml_parser_state_t *start;
+ /** The end of the stack. */
+ yaml_parser_state_t *end;
+ /** The top of the stack. */
+ yaml_parser_state_t *top;
+ } states;
+
+ /** The current parser state. */
+ yaml_parser_state_t state;
+
+ /** The stack of marks. */
+ struct {
+ /** The beginning of the stack. */
+ yaml_mark_t *start;
+ /** The end of the stack. */
+ yaml_mark_t *end;
+ /** The top of the stack. */
+ yaml_mark_t *top;
+ } marks;
+
+ /** The list of TAG directives. */
+ struct {
+ /** The beginning of the list. */
+ yaml_tag_directive_t *start;
+ /** The end of the list. */
+ yaml_tag_directive_t *end;
+ /** The top of the list. */
+ yaml_tag_directive_t *top;
+ } tag_directives;
+
+ /**
+ * @}
+ */
+
+ /**
+ * @name Dumper stuff
+ * @{
+ */
+
+ /** The alias data. */
+ struct {
+ /** The beginning of the list. */
+ yaml_alias_data_t *start;
+ /** The end of the list. */
+ yaml_alias_data_t *end;
+ /** The top of the list. */
+ yaml_alias_data_t *top;
+ } aliases;
+
+ /** The currently parsed document. */
+ yaml_document_t *document;
+
+ /**
+ * @}
+ */
+
+} yaml_parser_t;
+
+/**
+ * Initialize a parser.
+ *
+ * This function creates a new parser object. An application is responsible
+ * for destroying the object using the yaml_parser_delete() function.
+ *
+ * @param[out] parser An empty parser object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_initialize(yaml_parser_t *parser);
+
+/**
+ * Destroy a parser.
+ *
+ * @param[in,out] parser A parser object.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_delete(yaml_parser_t *parser);
+
+/**
+ * Set a string input.
+ *
+ * Note that the @a input pointer must be valid while the @a parser object
+ * exists. The application is responsible for destroing @a input after
+ * destroying the @a parser.
+ *
+ * @param[in,out] parser A parser object.
+ * @param[in] input A source data.
+ * @param[in] size The length of the source data in bytes.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_set_input_string(yaml_parser_t *parser,
+ const unsigned char *input, size_t size);
+
+/**
+ * Set a file input.
+ *
+ * @a file should be a file object open for reading. The application is
+ * responsible for closing the @a file.
+ *
+ * @param[in,out] parser A parser object.
+ * @param[in] file An open file.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file);
+
+/**
+ * Set a generic input handler.
+ *
+ * @param[in,out] parser A parser object.
+ * @param[in] handler A read handler.
+ * @param[in] data Any application data for passing to the read
+ * handler.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_set_input(yaml_parser_t *parser,
+ yaml_read_handler_t *handler, void *data);
+
+/**
+ * Set the source encoding.
+ *
+ * @param[in,out] parser A parser object.
+ * @param[in] encoding The source encoding.
+ */
+
+YAML_DECLARE(void)
+yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding);
+
+/**
+ * Scan the input stream and produce the next token.
+ *
+ * Call the function subsequently to produce a sequence of tokens corresponding
+ * to the input stream. The initial token has the type
+ * @c YAML_STREAM_START_TOKEN while the ending token has the type
+ * @c YAML_STREAM_END_TOKEN.
+ *
+ * An application is responsible for freeing any buffers associated with the
+ * produced token object using the @c yaml_token_delete function.
+ *
+ * An application must not alternate the calls of yaml_parser_scan() with the
+ * calls of yaml_parser_parse() or yaml_parser_load(). Doing this will break
+ * the parser.
+ *
+ * @param[in,out] parser A parser object.
+ * @param[out] token An empty token object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token);
+
+/**
+ * Parse the input stream and produce the next parsing event.
+ *
+ * Call the function subsequently to produce a sequence of events corresponding
+ * to the input stream. The initial event has the type
+ * @c YAML_STREAM_START_EVENT while the ending event has the type
+ * @c YAML_STREAM_END_EVENT.
+ *
+ * An application is responsible for freeing any buffers associated with the
+ * produced event object using the yaml_event_delete() function.
+ *
+ * An application must not alternate the calls of yaml_parser_parse() with the
+ * calls of yaml_parser_scan() or yaml_parser_load(). Doing this will break the
+ * parser.
+ *
+ * @param[in,out] parser A parser object.
+ * @param[out] event An empty event object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event);
+
+/**
+ * Parse the input stream and produce the next YAML document.
+ *
+ * Call this function subsequently to produce a sequence of documents
+ * constituting the input stream.
+ *
+ * If the produced document has no root node, it means that the document
+ * end has been reached.
+ *
+ * An application is responsible for freeing any data associated with the
+ * produced document object using the yaml_document_delete() function.
+ *
+ * An application must not alternate the calls of yaml_parser_load() with the
+ * calls of yaml_parser_scan() or yaml_parser_parse(). Doing this will break
+ * the parser.
+ *
+ * @param[in,out] parser A parser object.
+ * @param[out] document An empty document object.
+ *
+ * @return @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);
+
+/** @} */
+
+/**
+ * @defgroup emitter Emitter Definitions
+ * @{
+ */
+
+/**
+ * The prototype of a write handler.
+ *
+ * The write handler is called when the emitter needs to flush the accumulated
+ * characters to the output. The handler should write @a size bytes of the
+ * @a buffer to the output.
+ *
+ * @param[in,out] data A pointer to an application data specified by
+ * yaml_emitter_set_output().
+ * @param[in] buffer The buffer with bytes to be written.
+ * @param[in] size The size of the buffer.
+ *
+ * @returns On success, the handler should return @c 1. If the handler failed,
+ * the returned value should be @c 0.
+ */
+
+typedef int yaml_write_handler_t(void *data, unsigned char *buffer, size_t size);
+
+/** The emitter states. */
+typedef enum yaml_emitter_state_e {
+ /** Expect STREAM-START. */
+ YAML_EMIT_STREAM_START_STATE,
+ /** Expect the first DOCUMENT-START or STREAM-END. */
+ YAML_EMIT_FIRST_DOCUMENT_START_STATE,
+ /** Expect DOCUMENT-START or STREAM-END. */
+ YAML_EMIT_DOCUMENT_START_STATE,
+ /** Expect the content of a document. */
+ YAML_EMIT_DOCUMENT_CONTENT_STATE,
+ /** Expect DOCUMENT-END. */
+ YAML_EMIT_DOCUMENT_END_STATE,
+ /** Expect the first item of a flow sequence. */
+ YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE,
+ /** Expect an item of a flow sequence. */
+ YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE,
+ /** Expect the first key of a flow mapping. */
+ YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE,
+ /** Expect a key of a flow mapping. */
+ YAML_EMIT_FLOW_MAPPING_KEY_STATE,
+ /** Expect a value for a simple key of a flow mapping. */
+ YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE,
+ /** Expect a value of a flow mapping. */
+ YAML_EMIT_FLOW_MAPPING_VALUE_STATE,
+ /** Expect the first item of a block sequence. */
+ YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE,
+ /** Expect an item of a block sequence. */
+ YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE,
+ /** Expect the first key of a block mapping. */
+ YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE,
+ /** Expect the key of a block mapping. */
+ YAML_EMIT_BLOCK_MAPPING_KEY_STATE,
+ /** Expect a value for a simple key of a block mapping. */
+ YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE,
+ /** Expect a value of a block mapping. */
+ YAML_EMIT_BLOCK_MAPPING_VALUE_STATE,
+ /** Expect nothing. */
+ YAML_EMIT_END_STATE
+} yaml_emitter_state_t;
+
+/**
+ * The emitter structure.
+ *
+ * All members are internal. Manage the structure using the @c yaml_emitter_
+ * family of functions.
+ */
+
+typedef struct yaml_emitter_s {
+
+ /**
+ * @name Error handling
+ * @{
+ */
+
+ /** Error type. */
+ yaml_error_type_t error;
+ /** Error description. */
+ const char *problem;
+
+ /**
+ * @}
+ */
+
+ /**
+ * @name Writer stuff
+ * @{
+ */
+
+ /** Write handler. */
+ yaml_write_handler_t *write_handler;
+
+ /** A pointer for passing to the white handler. */
+ void *write_handler_data;
+
+ /** Standard (string or file) output data. */
+ union {
+ /** String output data. */
+ struct {
+ /** The buffer pointer. */
+ unsigned char *buffer;
+ /** The buffer size. */
+ size_t size;
+ /** The number of written bytes. */
+ size_t *size_written;
+ } string;
+
+ /** File output data. */
+ FILE *file;
+ } output;
+
+ /** The working buffer. */
+ struct {
+ /** The beginning of the buffer. */
+ yaml_char_t *start;
+ /** The end of the buffer. */
+ yaml_char_t *end;
+ /** The current position of the buffer. */
+ yaml_char_t *pointer;
+ /** The last filled position of the buffer. */
+ yaml_char_t *last;
+ } buffer;
+
+ /** The raw buffer. */
+ struct {
+ /** The beginning of the buffer. */
+ unsigned char *start;
+ /** The end of the buffer. */
+ unsigned char *end;
+ /** The current position of the buffer. */
+ unsigned char *pointer;
+ /** The last filled position of the buffer. */
+ unsigned char *last;
+ } raw_buffer;
+
+ /** The stream encoding. */
+ yaml_encoding_t encoding;
+
+ /**
+ * @}
+ */
+
+ /**
+ * @name Emitter stuff
+ * @{
+ */
+
+ /** If the output is in the canonical style? */
+ int canonical;
+ /** The number of indentation spaces. */
+ int best_indent;
+ /** The preferred width of the output lines. */
+ int best_width;
+ /** Allow unescaped non-ASCII characters? */
+ int unicode;
+ /** The preferred line break. */
+ yaml_break_t line_break;
+
+ /** The stack of states. */
+ struct {
+ /** The beginning of the stack. */
+ yaml_emitter_state_t *start;
+ /** The end of the stack. */
+ yaml_emitter_state_t *end;
+ /** The top of the stack. */
+ yaml_emitter_state_t *top;
+ } states;
+
+ /** The current emitter state. */
+ yaml_emitter_state_t state;
+
+ /** The event queue. */
+ struct {
+ /** The beginning of the event queue. */
+ yaml_event_t *start;
+ /** The end of the event queue. */
+ yaml_event_t *end;
+ /** The head of the event queue. */
+ yaml_event_t *head;
+ /** The tail of the event queue. */
+ yaml_event_t *tail;
+ } events;
+
+ /** The stack of indentation levels. */
+ struct {
+ /** The beginning of the stack. */
+ int *start;
+ /** The end of the stack. */
+ int *end;
+ /** The top of the stack. */
+ int *top;
+ } indents;
+
+ /** The list of tag directives. */
+ struct {
+ /** The beginning of the list. */
+ yaml_tag_directive_t *start;
+ /** The end of the list. */
+ yaml_tag_directive_t *end;
+ /** The top of the list. */
+ yaml_tag_directive_t *top;
+ } tag_directives;
+
+ /** The current indentation level. */
+ int indent;
+
+ /** The current flow level. */
+ int flow_level;
+
+ /** Is it the document root context? */
+ int root_context;
+ /** Is it a sequence context? */
+ int sequence_context;
+ /** Is it a mapping context? */
+ int mapping_context;
+ /** Is it a simple mapping key context? */
+ int simple_key_context;
+
+ /** The current line. */
+ int line;
+ /** The current column. */
+ int column;
+ /** If the last character was a whitespace? */
+ int whitespace;
+ /** If the last character was an indentation character (' ', '-', '?', ':')? */
+ int indention;
+ /** If an explicit document end is required? */
+ int open_ended;
+
+ /** Anchor analysis. */
+ struct {
+ /** The anchor value. */
+ yaml_char_t *anchor;
+ /** The anchor length. */
+ size_t anchor_length;
+ /** Is it an alias? */
+ int alias;
+ } anchor_data;
+
+ /** Tag analysis. */
+ struct {
+ /** The tag handle. */
+ yaml_char_t *handle;
+ /** The tag handle length. */
+ size_t handle_length;
+ /** The tag suffix. */
+ yaml_char_t *suffix;
+ /** The tag suffix length. */
+ size_t suffix_length;
+ } tag_data;
+
+ /** Scalar analysis. */
+ struct {
+ /** The scalar value. */
+ yaml_char_t *value;
+ /** The scalar length. */
+ size_t length;
+ /** Does the scalar contain line breaks? */
+ int multiline;
+ /** Can the scalar be expessed in the flow plain style? */
+ int flow_plain_allowed;
+ /** Can the scalar be expressed in the block plain style? */
+ int block_plain_allowed;
+ /** Can the scalar be expressed in the single quoted style? */
+ int single_quoted_allowed;
+ /** Can the scalar be expressed in the literal or folded styles? */
+ int block_allowed;
+ /** The output style. */
+ yaml_scalar_style_t style;
+ } scalar_data;
+
+ /**
+ * @}
+ */
+
+ /**
+ * @name Dumper stuff
+ * @{
+ */
+
+ /** If the stream was already opened? */
+ int opened;
+ /** If the stream was already closed? */
+ int closed;
+
+ /** The information associated with the document nodes. */
+ struct {
+ /** The number of references. */
+ int references;
+ /** The anchor id. */
+ int anchor;
+ /** If the node has been emitted? */
+ int serialized;
+ } *anchors;
+
+ /** The last assigned anchor id. */
+ int last_anchor_id;
+
+ /** The currently emitted document. */
+ yaml_document_t *document;
+
+ /**
+ * @}
+ */
+
+} yaml_emitter_t;
+
+/**
+ * Initialize an emitter.
+ *
+ * This function creates a new emitter object. An application is responsible
+ * for destroying the object using the yaml_emitter_delete() function.
+ *
+ * @param[out] emitter An empty parser object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_initialize(yaml_emitter_t *emitter);
+
+/**
+ * Destroy an emitter.
+ *
+ * @param[in,out] emitter An emitter object.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_delete(yaml_emitter_t *emitter);
+
+/**
+ * Set a string output.
+ *
+ * The emitter will write the output characters to the @a output buffer of the
+ * size @a size. The emitter will set @a size_written to the number of written
+ * bytes. If the buffer is smaller than required, the emitter produces the
+ * YAML_WRITE_ERROR error.
+ *
+ * @param[in,out] emitter An emitter object.
+ * @param[in] output An output buffer.
+ * @param[in] size The buffer size.
+ * @param[in] size_written The pointer to save the number of written
+ * bytes.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_output_string(yaml_emitter_t *emitter,
+ unsigned char *output, size_t size, size_t *size_written);
+
+/**
+ * Set a file output.
+ *
+ * @a file should be a file object open for writing. The application is
+ * responsible for closing the @a file.
+ *
+ * @param[in,out] emitter An emitter object.
+ * @param[in] file An open file.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file);
+
+/**
+ * Set a generic output handler.
+ *
+ * @param[in,out] emitter An emitter object.
+ * @param[in] handler A write handler.
+ * @param[in] data Any application data for passing to the write
+ * handler.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_output(yaml_emitter_t *emitter,
+ yaml_write_handler_t *handler, void *data);
+
+/**
+ * Set the output encoding.
+ *
+ * @param[in,out] emitter An emitter object.
+ * @param[in] encoding The output encoding.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding);
+
+/**
+ * Set if the output should be in the "canonical" format as in the YAML
+ * specification.
+ *
+ * @param[in,out] emitter An emitter object.
+ * @param[in] canonical If the output is canonical.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical);
+
+/**
+ * Set the intendation increment.
+ *
+ * @param[in,out] emitter An emitter object.
+ * @param[in] indent The indentation increment (1 < . < 10).
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent);
+
+/**
+ * Set the preferred line width. @c -1 means unlimited.
+ *
+ * @param[in,out] emitter An emitter object.
+ * @param[in] width The preferred line width.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_width(yaml_emitter_t *emitter, int width);
+
+/**
+ * Set if unescaped non-ASCII characters are allowed.
+ *
+ * @param[in,out] emitter An emitter object.
+ * @param[in] unicode If unescaped Unicode characters are allowed.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode);
+
+/**
+ * Set the preferred line break.
+ *
+ * @param[in,out] emitter An emitter object.
+ * @param[in] line_break The preferred line break.
+ */
+
+YAML_DECLARE(void)
+yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break);
+
+/**
+ * Emit an event.
+ *
+ * The event object may be generated using the yaml_parser_parse() function.
+ * The emitter takes the responsibility for the event object and destroys its
+ * content after it is emitted. The event object is destroyed even if the
+ * function fails.
+ *
+ * @param[in,out] emitter An emitter object.
+ * @param[in,out] event An event object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event);
+
+/**
+ * Start a YAML stream.
+ *
+ * This function should be used before yaml_emitter_dump() is called.
+ *
+ * @param[in,out] emitter An emitter object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_open(yaml_emitter_t *emitter);
+
+/**
+ * Finish a YAML stream.
+ *
+ * This function should be used after yaml_emitter_dump() is called.
+ *
+ * @param[in,out] emitter An emitter object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_close(yaml_emitter_t *emitter);
+
+/**
+ * Emit a YAML document.
+ *
+ * The documen object may be generated using the yaml_parser_load() function
+ * or the yaml_document_initialize() function. The emitter takes the
+ * responsibility for the document object and destoys its content after
+ * it is emitted. The document object is destroyedeven if the function fails.
+ *
+ * @param[in,out] emitter An emitter object.
+ * @param[in,out] document A document object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document);
+
+/**
+ * Flush the accumulated characters to the output.
+ *
+ * @param[in,out] emitter An emitter object.
+ *
+ * @returns @c 1 if the function succeeded, @c 0 on error.
+ */
+
+YAML_DECLARE(int)
+yaml_emitter_flush(yaml_emitter_t *emitter);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef YAML_H */
+
diff --git a/libyaml/yaml_private.h b/libyaml/yaml_private.h
new file mode 100644
index 0000000..31ed23c
--- /dev/null
+++ b/libyaml/yaml_private.h
@@ -0,0 +1,646 @@
+
+#if HAVE_CONFIG_H
+#include
+#endif
+
+#include "libyaml/yaml.h"
+
+#include
+#include
+
+
+#define YAML_titleVersion_STRING "0.1.4"
+#define YAML_titleVersion_MAJOR 0
+#define YAML_titleVersion_MINOR 1
+#define YAML_titleVersion_PATCH 4
+
+/*
+ * Memory management.
+ */
+
+YAML_DECLARE(void *)
+yaml_malloc(size_t size);
+
+YAML_DECLARE(void *)
+yaml_realloc(void *ptr, size_t size);
+
+YAML_DECLARE(void)
+yaml_free(void *ptr);
+
+YAML_DECLARE(yaml_char_t *)
+yaml_strdup(const yaml_char_t *);
+
+/*
+ * Reader: Ensure that the buffer contains at least `length` characters.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_update_buffer(yaml_parser_t *parser, size_t length);
+
+/*
+ * Scanner: Ensure that the token stack contains at least one token ready.
+ */
+
+YAML_DECLARE(int)
+yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
+
+/*
+ * The size of the input raw buffer.
+ */
+
+#define INPUT_RAW_BUFFER_SIZE 16384
+
+/*
+ * The size of the input buffer.
+ *
+ * It should be possible to decode the whole raw buffer.
+ */
+
+#define INPUT_BUFFER_SIZE (INPUT_RAW_BUFFER_SIZE*3)
+
+/*
+ * The size of the output buffer.
+ */
+
+#define OUTPUT_BUFFER_SIZE 16384
+
+/*
+ * The size of the output raw buffer.
+ *
+ * It should be possible to encode the whole output buffer.
+ */
+
+#define OUTPUT_RAW_BUFFER_SIZE (OUTPUT_BUFFER_SIZE*2+2)
+
+/*
+ * The size of other stacks and queues.
+ */
+
+#define INITIAL_STACK_SIZE 16
+#define INITIAL_QUEUE_SIZE 16
+#define INITIAL_STRING_SIZE 16
+
+/*
+ * Buffer management.
+ */
+
+#define BUFFER_INIT(context,buffer,size) \
+ (((buffer).start = yaml_malloc(size)) ? \
+ ((buffer).last = (buffer).pointer = (buffer).start, \
+ (buffer).end = (buffer).start+(size), \
+ 1) : \
+ ((context)->error = YAML_MEMORY_ERROR, \
+ 0))
+
+#define BUFFER_DEL(context,buffer) \
+ (yaml_free((buffer).start), \
+ (buffer).start = (buffer).pointer = (buffer).end = 0)
+
+/*
+ * String management.
+ */
+
+typedef struct {
+ yaml_char_t *start;
+ yaml_char_t *end;
+ yaml_char_t *pointer;
+} yaml_string_t;
+
+YAML_DECLARE(int)
+yaml_string_extend(yaml_char_t **start,
+ yaml_char_t **pointer, yaml_char_t **end);
+
+YAML_DECLARE(int)
+yaml_string_join(
+ yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
+ yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end);
+
+#define NULL_STRING { NULL, NULL, NULL }
+
+#define STRING(string,length) { (string), (string)+(length), (string) }
+
+#define STRING_ASSIGN(value,string,length) \
+ ((value).start = (string), \
+ (value).end = (string)+(length), \
+ (value).pointer = (string))
+
+#define STRING_INIT(context,string,size) \
+ (((string).start = yaml_malloc(size)) ? \
+ ((string).pointer = (string).start, \
+ (string).end = (string).start+(size), \
+ memset((string).start, 0, (size)), \
+ 1) : \
+ ((context)->error = YAML_MEMORY_ERROR, \
+ 0))
+
+#define STRING_DEL(context,string) \
+ (yaml_free((string).start), \
+ (string).start = (string).pointer = (string).end = 0)
+
+#define STRING_EXTEND(context,string) \
+ (((string).pointer+5 < (string).end) \
+ || yaml_string_extend(&(string).start, \
+ &(string).pointer, &(string).end))
+
+#define CLEAR(context,string) \
+ ((string).pointer = (string).start, \
+ memset((string).start, 0, (string).end-(string).start))
+
+#define JOIN(context,string_a,string_b) \
+ ((yaml_string_join(&(string_a).start, &(string_a).pointer, \
+ &(string_a).end, &(string_b).start, \
+ &(string_b).pointer, &(string_b).end)) ? \
+ ((string_b).pointer = (string_b).start, \
+ 1) : \
+ ((context)->error = YAML_MEMORY_ERROR, \
+ 0))
+
+/*
+ * String check operations.
+ */
+
+/*
+ * Check the octet at the specified position.
+ */
+
+#define CHECK_AT(string,octet,offset) \
+ ((string).pointer[offset] == (yaml_char_t)(octet))
+
+/*
+ * Check the current octet in the buffer.
+ */
+
+#define CHECK(string,octet) CHECK_AT((string),(octet),0)
+
+/*
+ * Check if the character at the specified position is an alphabetical
+ * character, a digit, '_', or '-'.
+ */
+
+#define IS_ALPHA_AT(string,offset) \
+ (((string).pointer[offset] >= (yaml_char_t) '0' && \
+ (string).pointer[offset] <= (yaml_char_t) '9') || \
+ ((string).pointer[offset] >= (yaml_char_t) 'A' && \
+ (string).pointer[offset] <= (yaml_char_t) 'Z') || \
+ ((string).pointer[offset] >= (yaml_char_t) 'a' && \
+ (string).pointer[offset] <= (yaml_char_t) 'z') || \
+ (string).pointer[offset] == '_' || \
+ (string).pointer[offset] == '-')
+
+#define IS_ALPHA(string) IS_ALPHA_AT((string),0)
+
+/*
+ * Check if the character at the specified position is a digit.
+ */
+
+#define IS_DIGIT_AT(string,offset) \
+ (((string).pointer[offset] >= (yaml_char_t) '0' && \
+ (string).pointer[offset] <= (yaml_char_t) '9'))
+
+#define IS_DIGIT(string) IS_DIGIT_AT((string),0)
+
+/*
+ * Get the value of a digit.
+ */
+
+#define AS_DIGIT_AT(string,offset) \
+ ((string).pointer[offset] - (yaml_char_t) '0')
+
+#define AS_DIGIT(string) AS_DIGIT_AT((string),0)
+
+/*
+ * Check if the character at the specified position is a hex-digit.
+ */
+
+#define IS_HEX_AT(string,offset) \
+ (((string).pointer[offset] >= (yaml_char_t) '0' && \
+ (string).pointer[offset] <= (yaml_char_t) '9') || \
+ ((string).pointer[offset] >= (yaml_char_t) 'A' && \
+ (string).pointer[offset] <= (yaml_char_t) 'F') || \
+ ((string).pointer[offset] >= (yaml_char_t) 'a' && \
+ (string).pointer[offset] <= (yaml_char_t) 'f'))
+
+#define IS_HEX(string) IS_HEX_AT((string),0)
+
+/*
+ * Get the value of a hex-digit.
+ */
+
+#define AS_HEX_AT(string,offset) \
+ (((string).pointer[offset] >= (yaml_char_t) 'A' && \
+ (string).pointer[offset] <= (yaml_char_t) 'F') ? \
+ ((string).pointer[offset] - (yaml_char_t) 'A' + 10) : \
+ ((string).pointer[offset] >= (yaml_char_t) 'a' && \
+ (string).pointer[offset] <= (yaml_char_t) 'f') ? \
+ ((string).pointer[offset] - (yaml_char_t) 'a' + 10) : \
+ ((string).pointer[offset] - (yaml_char_t) '0'))
+
+#define AS_HEX(string) AS_HEX_AT((string),0)
+
+/*
+ * Check if the character is ASCII.
+ */
+
+#define IS_ASCII_AT(string,offset) \
+ ((string).pointer[offset] <= (yaml_char_t) '\x7F')
+
+#define IS_ASCII(string) IS_ASCII_AT((string),0)
+
+/*
+ * Check if the character can be printed unescaped.
+ */
+
+#define IS_PRINTABLE_AT(string,offset) \
+ (((string).pointer[offset] == 0x0A) /* . == #x0A */ \
+ || ((string).pointer[offset] >= 0x20 /* #x20 <= . <= #x7E */ \
+ && (string).pointer[offset] <= 0x7E) \
+ || ((string).pointer[offset] == 0xC2 /* #0xA0 <= . <= #xD7FF */ \
+ && (string).pointer[offset+1] >= 0xA0) \
+ || ((string).pointer[offset] > 0xC2 \
+ && (string).pointer[offset] < 0xED) \
+ || ((string).pointer[offset] == 0xED \
+ && (string).pointer[offset+1] < 0xA0) \
+ || ((string).pointer[offset] == 0xEE) \
+ || ((string).pointer[offset] == 0xEF /* #xE000 <= . <= #xFFFD */ \
+ && !((string).pointer[offset+1] == 0xBB /* && . != #xFEFF */ \
+ && (string).pointer[offset+2] == 0xBF) \
+ && !((string).pointer[offset+1] == 0xBF \
+ && ((string).pointer[offset+2] == 0xBE \
+ || (string).pointer[offset+2] == 0xBF))))
+
+#define IS_PRINTABLE(string) IS_PRINTABLE_AT((string),0)
+
+/*
+ * Check if the character at the specified position is NUL.
+ */
+
+#define IS_Z_AT(string,offset) CHECK_AT((string),'\0',(offset))
+
+#define IS_Z(string) IS_Z_AT((string),0)
+
+/*
+ * Check if the character at the specified position is BOM.
+ */
+
+#define IS_BOM_AT(string,offset) \
+ (CHECK_AT((string),'\xEF',(offset)) \
+ && CHECK_AT((string),'\xBB',(offset)+1) \
+ && CHECK_AT((string),'\xBF',(offset)+2)) /* BOM (#xFEFF) */
+
+#define IS_BOM(string) IS_BOM_AT(string,0)
+
+/*
+ * Check if the character at the specified position is space.
+ */
+
+#define IS_SPACE_AT(string,offset) CHECK_AT((string),' ',(offset))
+
+#define IS_SPACE(string) IS_SPACE_AT((string),0)
+
+/*
+ * Check if the character at the specified position is tab.
+ */
+
+#define IS_TAB_AT(string,offset) CHECK_AT((string),'\t',(offset))
+
+#define IS_TAB(string) IS_TAB_AT((string),0)
+
+/*
+ * Check if the character at the specified position is blank (space or tab).
+ */
+
+#define IS_BLANK_AT(string,offset) \
+ (IS_SPACE_AT((string),(offset)) || IS_TAB_AT((string),(offset)))
+
+#define IS_BLANK(string) IS_BLANK_AT((string),0)
+
+/*
+ * Check if the character at the specified position is a line break.
+ */
+
+#define IS_BREAK_AT(string,offset) \
+ (CHECK_AT((string),'\r',(offset)) /* CR (#xD)*/ \
+ || CHECK_AT((string),'\n',(offset)) /* LF (#xA) */ \
+ || (CHECK_AT((string),'\xC2',(offset)) \
+ && CHECK_AT((string),'\x85',(offset)+1)) /* NEL (#x85) */ \
+ || (CHECK_AT((string),'\xE2',(offset)) \
+ && CHECK_AT((string),'\x80',(offset)+1) \
+ && CHECK_AT((string),'\xA8',(offset)+2)) /* LS (#x2028) */ \
+ || (CHECK_AT((string),'\xE2',(offset)) \
+ && CHECK_AT((string),'\x80',(offset)+1) \
+ && CHECK_AT((string),'\xA9',(offset)+2))) /* PS (#x2029) */
+
+#define IS_BREAK(string) IS_BREAK_AT((string),0)
+
+#define IS_CRLF_AT(string,offset) \
+ (CHECK_AT((string),'\r',(offset)) && CHECK_AT((string),'\n',(offset)+1))
+
+#define IS_CRLF(string) IS_CRLF_AT((string),0)
+
+/*
+ * Check if the character is a line break or NUL.
+ */
+
+#define IS_BREAKZ_AT(string,offset) \
+ (IS_BREAK_AT((string),(offset)) || IS_Z_AT((string),(offset)))
+
+#define IS_BREAKZ(string) IS_BREAKZ_AT((string),0)
+
+/*
+ * Check if the character is a line break, space, or NUL.
+ */
+
+#define IS_SPACEZ_AT(string,offset) \
+ (IS_SPACE_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset)))
+
+#define IS_SPACEZ(string) IS_SPACEZ_AT((string),0)
+
+/*
+ * Check if the character is a line break, space, tab, or NUL.
+ */
+
+#define IS_BLANKZ_AT(string,offset) \
+ (IS_BLANK_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset)))
+
+#define IS_BLANKZ(string) IS_BLANKZ_AT((string),0)
+
+/*
+ * Determine the width of the character.
+ */
+
+#define WIDTH_AT(string,offset) \
+ (((string).pointer[offset] & 0x80) == 0x00 ? 1 : \
+ ((string).pointer[offset] & 0xE0) == 0xC0 ? 2 : \
+ ((string).pointer[offset] & 0xF0) == 0xE0 ? 3 : \
+ ((string).pointer[offset] & 0xF8) == 0xF0 ? 4 : 0)
+
+#define WIDTH(string) WIDTH_AT((string),0)
+
+/*
+ * Move the string pointer to the next character.
+ */
+
+#define MOVE(string) ((string).pointer += WIDTH((string)))
+
+/*
+ * Copy a character and move the pointers of both strings.
+ */
+
+#define COPY(string_a,string_b) \
+ ((*(string_b).pointer & 0x80) == 0x00 ? \
+ (*((string_a).pointer++) = *((string_b).pointer++)) : \
+ (*(string_b).pointer & 0xE0) == 0xC0 ? \
+ (*((string_a).pointer++) = *((string_b).pointer++), \
+ *((string_a).pointer++) = *((string_b).pointer++)) : \
+ (*(string_b).pointer & 0xF0) == 0xE0 ? \
+ (*((string_a).pointer++) = *((string_b).pointer++), \
+ *((string_a).pointer++) = *((string_b).pointer++), \
+ *((string_a).pointer++) = *((string_b).pointer++)) : \
+ (*(string_b).pointer & 0xF8) == 0xF0 ? \
+ (*((string_a).pointer++) = *((string_b).pointer++), \
+ *((string_a).pointer++) = *((string_b).pointer++), \
+ *((string_a).pointer++) = *((string_b).pointer++), \
+ *((string_a).pointer++) = *((string_b).pointer++)) : 0)
+
+/*
+ * Stack and queue management.
+ */
+
+YAML_DECLARE(int)
+yaml_stack_extend(void **start, void **top, void **end);
+
+YAML_DECLARE(int)
+yaml_queue_extend(void **start, void **head, void **tail, void **end);
+
+#define STACK_INIT(context,stack,size) \
+ (((stack).start = yaml_malloc((size)*sizeof(*(stack).start))) ? \
+ ((stack).top = (stack).start, \
+ (stack).end = (stack).start+(size), \
+ 1) : \
+ ((context)->error = YAML_MEMORY_ERROR, \
+ 0))
+
+#define STACK_DEL(context,stack) \
+ (yaml_free((stack).start), \
+ (stack).start = (stack).top = (stack).end = 0)
+
+#define STACK_EMPTY(context,stack) \
+ ((stack).start == (stack).top)
+
+#define PUSH(context,stack,value) \
+ (((stack).top != (stack).end \
+ || yaml_stack_extend((void **)&(stack).start, \
+ (void **)&(stack).top, (void **)&(stack).end)) ? \
+ (*((stack).top++) = value, \
+ 1) : \
+ ((context)->error = YAML_MEMORY_ERROR, \
+ 0))
+
+#define POP(context,stack) \
+ (*(--(stack).top))
+
+#define QUEUE_INIT(context,queue,size) \
+ (((queue).start = yaml_malloc((size)*sizeof(*(queue).start))) ? \
+ ((queue).head = (queue).tail = (queue).start, \
+ (queue).end = (queue).start+(size), \
+ 1) : \
+ ((context)->error = YAML_MEMORY_ERROR, \
+ 0))
+
+#define QUEUE_DEL(context,queue) \
+ (yaml_free((queue).start), \
+ (queue).start = (queue).head = (queue).tail = (queue).end = 0)
+
+#define QUEUE_EMPTY(context,queue) \
+ ((queue).head == (queue).tail)
+
+#define ENQUEUE(context,queue,value) \
+ (((queue).tail != (queue).end \
+ || yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \
+ (void **)&(queue).tail, (void **)&(queue).end)) ? \
+ (*((queue).tail++) = value, \
+ 1) : \
+ ((context)->error = YAML_MEMORY_ERROR, \
+ 0))
+
+#define DEQUEUE(context,queue) \
+ (*((queue).head++))
+
+#define QUEUE_INSERT(context,queue,index,value) \
+ (((queue).tail != (queue).end \
+ || yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \
+ (void **)&(queue).tail, (void **)&(queue).end)) ? \
+ (memmove((queue).head+(index)+1,(queue).head+(index), \
+ ((queue).tail-(queue).head-(index))*sizeof(*(queue).start)), \
+ *((queue).head+(index)) = value, \
+ (queue).tail++, \
+ 1) : \
+ ((context)->error = YAML_MEMORY_ERROR, \
+ 0))
+
+/*
+ * Token initializers.
+ */
+
+#define TOKEN_INIT(token,token_type,token_start_mark,token_end_mark) \
+ (memset(&(token), 0, sizeof(yaml_token_t)), \
+ (token).type = (token_type), \
+ (token).start_mark = (token_start_mark), \
+ (token).end_mark = (token_end_mark))
+
+#define STREAM_START_TOKEN_INIT(token,token_encoding,start_mark,end_mark) \
+ (TOKEN_INIT((token),YAML_STREAM_START_TOKEN,(start_mark),(end_mark)), \
+ (token).data.stream_start.encoding = (token_encoding))
+
+#define STREAM_END_TOKEN_INIT(token,start_mark,end_mark) \
+ (TOKEN_INIT((token),YAML_STREAM_END_TOKEN,(start_mark),(end_mark)))
+
+#define ALIAS_TOKEN_INIT(token,token_value,start_mark,end_mark) \
+ (TOKEN_INIT((token),YAML_ALIAS_TOKEN,(start_mark),(end_mark)), \
+ (token).data.alias.value = (token_value))
+
+#define ANCHOR_TOKEN_INIT(token,token_value,start_mark,end_mark) \
+ (TOKEN_INIT((token),YAML_ANCHOR_TOKEN,(start_mark),(end_mark)), \
+ (token).data.anchor.value = (token_value))
+
+#define TAG_TOKEN_INIT(token,token_handle,token_suffix,start_mark,end_mark) \
+ (TOKEN_INIT((token),YAML_TAG_TOKEN,(start_mark),(end_mark)), \
+ (token).data.tag.handle = (token_handle), \
+ (token).data.tag.suffix = (token_suffix))
+
+#define SCALAR_TOKEN_INIT(token,token_value,token_length,token_style,start_mark,end_mark) \
+ (TOKEN_INIT((token),YAML_SCALAR_TOKEN,(start_mark),(end_mark)), \
+ (token).data.scalar.value = (token_value), \
+ (token).data.scalar.length = (token_length), \
+ (token).data.scalar.style = (token_style))
+
+#define titleVersion_DIRECTIVE_TOKEN_INIT(token,token_major,token_minor,start_mark,end_mark) \
+ (TOKEN_INIT((token),YAML_titleVersion_DIRECTIVE_TOKEN,(start_mark),(end_mark)), \
+ (token).data.titleVersion_directive.major = (token_major), \
+ (token).data.titleVersion_directive.minor = (token_minor))
+
+#define TAG_DIRECTIVE_TOKEN_INIT(token,token_handle,token_prefix,start_mark,end_mark) \
+ (TOKEN_INIT((token),YAML_TAG_DIRECTIVE_TOKEN,(start_mark),(end_mark)), \
+ (token).data.tag_directive.handle = (token_handle), \
+ (token).data.tag_directive.prefix = (token_prefix))
+
+/*
+ * Event initializers.
+ */
+
+#define EVENT_INIT(event,event_type,event_start_mark,event_end_mark) \
+ (memset(&(event), 0, sizeof(yaml_event_t)), \
+ (event).type = (event_type), \
+ (event).start_mark = (event_start_mark), \
+ (event).end_mark = (event_end_mark))
+
+#define STREAM_START_EVENT_INIT(event,event_encoding,start_mark,end_mark) \
+ (EVENT_INIT((event),YAML_STREAM_START_EVENT,(start_mark),(end_mark)), \
+ (event).data.stream_start.encoding = (event_encoding))
+
+#define STREAM_END_EVENT_INIT(event,start_mark,end_mark) \
+ (EVENT_INIT((event),YAML_STREAM_END_EVENT,(start_mark),(end_mark)))
+
+#define DOCUMENT_START_EVENT_INIT(event,event_titleVersion_directive, \
+ event_tag_directives_start,event_tag_directives_end,event_implicit,start_mark,end_mark) \
+ (EVENT_INIT((event),YAML_DOCUMENT_START_EVENT,(start_mark),(end_mark)), \
+ (event).data.document_start.titleVersion_directive = (event_titleVersion_directive), \
+ (event).data.document_start.tag_directives.start = (event_tag_directives_start), \
+ (event).data.document_start.tag_directives.end = (event_tag_directives_end), \
+ (event).data.document_start.implicit = (event_implicit))
+
+#define DOCUMENT_END_EVENT_INIT(event,event_implicit,start_mark,end_mark) \
+ (EVENT_INIT((event),YAML_DOCUMENT_END_EVENT,(start_mark),(end_mark)), \
+ (event).data.document_end.implicit = (event_implicit))
+
+#define ALIAS_EVENT_INIT(event,event_anchor,start_mark,end_mark) \
+ (EVENT_INIT((event),YAML_ALIAS_EVENT,(start_mark),(end_mark)), \
+ (event).data.alias.anchor = (event_anchor))
+
+#define SCALAR_EVENT_INIT(event,event_anchor,event_tag,event_value,event_length, \
+ event_plain_implicit, event_quoted_implicit,event_style,start_mark,end_mark) \
+ (EVENT_INIT((event),YAML_SCALAR_EVENT,(start_mark),(end_mark)), \
+ (event).data.scalar.anchor = (event_anchor), \
+ (event).data.scalar.tag = (event_tag), \
+ (event).data.scalar.value = (event_value), \
+ (event).data.scalar.length = (event_length), \
+ (event).data.scalar.plain_implicit = (event_plain_implicit), \
+ (event).data.scalar.quoted_implicit = (event_quoted_implicit), \
+ (event).data.scalar.style = (event_style))
+
+#define SEQUENCE_START_EVENT_INIT(event,event_anchor,event_tag, \
+ event_implicit,event_style,start_mark,end_mark) \
+ (EVENT_INIT((event),YAML_SEQUENCE_START_EVENT,(start_mark),(end_mark)), \
+ (event).data.sequence_start.anchor = (event_anchor), \
+ (event).data.sequence_start.tag = (event_tag), \
+ (event).data.sequence_start.implicit = (event_implicit), \
+ (event).data.sequence_start.style = (event_style))
+
+#define SEQUENCE_END_EVENT_INIT(event,start_mark,end_mark) \
+ (EVENT_INIT((event),YAML_SEQUENCE_END_EVENT,(start_mark),(end_mark)))
+
+#define MAPPING_START_EVENT_INIT(event,event_anchor,event_tag, \
+ event_implicit,event_style,start_mark,end_mark) \
+ (EVENT_INIT((event),YAML_MAPPING_START_EVENT,(start_mark),(end_mark)), \
+ (event).data.mapping_start.anchor = (event_anchor), \
+ (event).data.mapping_start.tag = (event_tag), \
+ (event).data.mapping_start.implicit = (event_implicit), \
+ (event).data.mapping_start.style = (event_style))
+
+#define MAPPING_END_EVENT_INIT(event,start_mark,end_mark) \
+ (EVENT_INIT((event),YAML_MAPPING_END_EVENT,(start_mark),(end_mark)))
+
+/*
+ * Document initializer.
+ */
+
+#define DOCUMENT_INIT(document,document_nodes_start,document_nodes_end, \
+ document_titleVersion_directive,document_tag_directives_start, \
+ document_tag_directives_end,document_start_implicit, \
+ document_end_implicit,document_start_mark,document_end_mark) \
+ (memset(&(document), 0, sizeof(yaml_document_t)), \
+ (document).nodes.start = (document_nodes_start), \
+ (document).nodes.end = (document_nodes_end), \
+ (document).nodes.top = (document_nodes_start), \
+ (document).titleVersion_directive = (document_titleVersion_directive), \
+ (document).tag_directives.start = (document_tag_directives_start), \
+ (document).tag_directives.end = (document_tag_directives_end), \
+ (document).start_implicit = (document_start_implicit), \
+ (document).end_implicit = (document_end_implicit), \
+ (document).start_mark = (document_start_mark), \
+ (document).end_mark = (document_end_mark))
+
+/*
+ * Node initializers.
+ */
+
+#define NODE_INIT(node,node_type,node_tag,node_start_mark,node_end_mark) \
+ (memset(&(node), 0, sizeof(yaml_node_t)), \
+ (node).type = (node_type), \
+ (node).tag = (node_tag), \
+ (node).start_mark = (node_start_mark), \
+ (node).end_mark = (node_end_mark))
+
+#define SCALAR_NODE_INIT(node,node_tag,node_value,node_length, \
+ node_style,start_mark,end_mark) \
+ (NODE_INIT((node),YAML_SCALAR_NODE,(node_tag),(start_mark),(end_mark)), \
+ (node).data.scalar.value = (node_value), \
+ (node).data.scalar.length = (node_length), \
+ (node).data.scalar.style = (node_style))
+
+#define SEQUENCE_NODE_INIT(node,node_tag,node_items_start,node_items_end, \
+ node_style,start_mark,end_mark) \
+ (NODE_INIT((node),YAML_SEQUENCE_NODE,(node_tag),(start_mark),(end_mark)), \
+ (node).data.sequence.items.start = (node_items_start), \
+ (node).data.sequence.items.end = (node_items_end), \
+ (node).data.sequence.items.top = (node_items_start), \
+ (node).data.sequence.style = (node_style))
+
+#define MAPPING_NODE_INIT(node,node_tag,node_pairs_start,node_pairs_end, \
+ node_style,start_mark,end_mark) \
+ (NODE_INIT((node),YAML_MAPPING_NODE,(node_tag),(start_mark),(end_mark)), \
+ (node).data.mapping.pairs.start = (node_pairs_start), \
+ (node).data.mapping.pairs.end = (node_pairs_end), \
+ (node).data.mapping.pairs.top = (node_pairs_start), \
+ (node).data.mapping.style = (node_style))
+
diff --git a/logo_data.h b/logo_data.h
new file mode 100644
index 0000000..66ec98a
--- /dev/null
+++ b/logo_data.h
@@ -0,0 +1,29 @@
+#ifndef _LOGO_DATA_H_
+#define _LOGO_DATA_H_
+
+static const unsigned char Nintendo_LZ[0x2000] =
+{
+ 0x11, 0x48, 0x65, 0x00, 0x00, 0x64, 0x61, 0x72, 0x63, 0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x28, 0x65, 0x00, 0x00, 0x83, 0x30, 0x09, 0x1C, 0x04, 0x00, 0x00, 0x40, 0x20, 0x03, 0x30, 0x13, 0xAB, 0x30, 0x18, 0x15, 0x20, 0x1D, 0x02, 0xA0, 0x0B, 0x06, 0x20, 0x2B, 0x30, 0x18, 0x5A, 0x09, 0x20, 0x35, 0x10, 0x20, 0x39, 0x30, 0x2B, 0xF8, 0x20, 0x41, 0x54, 0x85, 0x30, 0x0B, 0x05, 0x00, 0x00, 0xEC, 0x20, 0x4D, 0x98, 0x30, 0x17, 0xD0, 0x20, 0x28, 0x30, 0x17, 0xDC, 0x30, 0x23, 0x07, 0x00, 0x00, 0xCC, 0x09, 0x0C, 0x00, 0x00, 0x20, 0x20, 0x51, 0x20, 0x14, 0x20, 0x2B, 0xA0, 0x20, 0x0B, 0x64, 0x20, 0x5D, 0x80, 0x20, 0x00, 0x00, 0x4C, 0x99, 0x20, 0x5C, 0xA8, 0x01, 0x50, 0x53, 0x20, 0x22, 0x00, 0xB2, 0x20, 0x75, 0x34, 0xE0, 0x22, 0x20, 0x13, 0x20, 0x74, 0xE2, 0x20, 0x81, 0xA0, 0x25, 0x13, 0x00, 0x00, 0x3C, 0x20, 0x68, 0x12, 0x02, 0x50, 0x77, 0x30, 0x8F, 0x41, 0x1C, 0x20, 0x90, 0x00, 0x36, 0x00, 0x00, 0x28, 0x20, 0xAB, 0x4D, 0x3E, 0x20, 0x9C, 0x80, 0x3A, 0x20, 0x0B, 0x20, 0xAD, 0x60, 0x30, 0x17, 0x54, 0x3C, 0x50, 0x17, 0x82, 0x30, 0x17, 0x40, 0x20, 0x23, 0x08, 0x00, 0x2D, 0x00, 0xA4, 0x30, 0x2F, 0x49, 0x20, 0x67, 0x20, 0xE9, 0xC4, 0x30, 0x3B, 0x56, 0x4A, 0x50, 0x17, 0xDC, 0x30, 0x3B, 0x52, 0x20, 0x47, 0x20, 0xE0, 0xF4, 0xB2, 0x30, 0x53, 0x55, 0x20, 0x53, 0x30, 0xD4, 0x00, 0x2E, 0x21, 0x13, 0x61, 0x02, 0x00, 0x6E, 0x00, 0x69, 0x00, 0x6D, 0x21, 0x1D, 0x4E, 0x82, 0x20, 0x07, 0x6E, 0x00, 0x74, 0x00, 0x65, 0x20, 0x11, 0x64, 0x0A, 0x00, 0x6F, 0x00, 0x4C, 0x20, 0x03, 0x67, 0x20, 0x07, 0x5F, 0x28, 0x00, 0x44, 0x20, 0x03, 0x30, 0x20, 0x01, 0x5F, 0x00, 0x53, 0x20, 0x00, 0x63, 0x40, 0x1F, 0x65, 0x00, 0x4F, 0x00, 0x75, 0xAB, 0x20, 0x2B, 0x41, 0x20, 0x43, 0x62, 0x20, 0x13, 0x6C, 0x40, 0x47, 0x02, 0x50, 0x43, 0x57, 0x42, 0x03, 0x20, 0x43, 0x43, 0x01, 0x80, 0x87, 0x55, 0x03, 0x20, 0xCB, 0x00, 0x90, 0x43, 0x01, 0x90, 0xCB, 0xD7, 0x00, 0x90, 0x87, 0xF0, 0xCB, 0x62, 0x21, 0x5D, 0x79, 0x21, 0x97, 0x01, 0x31, 0xA1, 0x71, 0x8D, 0xEA, 0x00, 0xF0, 0x2F, 0x71, 0x05, 0xD0, 0x2F, 0x74, 0x42, 0x09, 0x67, 0x23, 0x29, 0x33, 0xBD, 0x22, 0x01, 0x73, 0xA2, 0x01, 0xB0, 0x5B, 0x52, 0x2D, 0x00, 0x10, 0x21, 0x31, 0x01, 0x00, 0x21, 0x55, 0x32, 0x01, 0x00, 0x43, 0x33, 0xE0, 0x65, 0x4C, 0x23, 0x71, 0x4D, 0x22, 0xA3, 0x1F, 0x73, 0x00, 0x6B, 0x00, 0x40, 0x85, 0x30, 0x1F, 0x00, 0xB0, 0x17, 0xF0, 0x93, 0xF2, 0xE3, 0x41, 0x5F, 0x20, 0xB5, 0x32, 0x00, 0x38, 0x00, 0x78, 0x23, 0x68, 0x60, 0x34, 0xE0, 0xE1, 0x70, 0x02, 0x43, 0x4C, 0x41, 0x4E, 0xFF, 0x46, 0xFE, 0x23, 0xD0, 0x00, 0x02, 0x02, 0x34, 0x03, 0x33, 0x96, 0x70, 0x1D, 0x61, 0x74, 0x31, 0x23, 0x82, 0x44, 0x3E, 0x34, 0x59, 0x28, 0x33, 0x73, 0x10, 0xFF, 0xFF, 0xFF, 0x34, 0x4C, 0x53, 0x63, 0x65, 0x6E, 0x04, 0x65, 0x4F, 0x75, 0x74, 0x41, 0x24, 0x71, 0x47, 0x5F, 0x0C, 0x41, 0x5F, 0x30, 0x30, 0xA0, 0x4C, 0x40, 0x3B, 0x69, 0x31, 0xCD, 0x33, 0xA3, 0x50, 0x3F, 0x02, 0x00, 0x30, 0x59, 0x34, 0x9D, 0x68, 0x24, 0xA1, 0x00, 0x50, 0x5F, 0x4E, 0x69, 0x6E, 0x4C, 0x6F, 0x67, 0x70, 0x6F, 0xA0, 0x35, 0x34, 0xA0, 0x34, 0xBD, 0x43, 0x4C, 0x56, 0x43, 0x8F, 0x74, 0x3F, 0x00, 0x10, 0x02, 0x40, 0x87, 0x40, 0x0B, 0xD0, 0x5D, 0x20, 0x76, 0x20, 0x7F, 0x43, 0x34, 0xEC, 0x4E, 0x5F, 0x52, 0x6F, 0x6F, 0x73, 0x74, 0xD0, 0x7E, 0x00, 0x70, 0x4B, 0x80, 0x57, 0x00, 0x20, 0x20, 0x3B, 0x50, 0x3F, 0xF8, 0x00, 0x30, 0xFF, 0x34, 0xF7, 0xB0, 0xFF, 0x24, 0xD2, 0x80, 0xFF, 0x00, 0x00, 0x1E, 0xD5, 0x45, 0x4C, 0x70, 0xFF, 0x42, 0x40, 0xFF, 0x42, 0x00, 0x40, 0xFF, 0x9C, 0x80, 0x2D, 0xB2, 0x90, 0xFF, 0x5C, 0x01, 0xE0, 0xFF, 0x90, 0xB3, 0x34, 0xC2, 0x02, 0xD0, 0xF3, 0xC8, 0xFD, 0x20, 0xAA, 0xD0, 0xF3, 0x00, 0x70, 0xFF, 0xF1, 0xFF, 0x31, 0x39, 0x71, 0xFF, 0x65, 0x23, 0x31, 0xC5, 0xB1, 0xFF, 0x31, 0x84, 0x47, 0x5F, 0x43, 0x00, 0x81, 0xFF, 0x0F, 0xE1, 0xFF, 0x99, 0x02, 0x90, 0xFF, 0x12, 0xC3, 0x02, 0x31, 0xF3, 0x92, 0x3F, 0x80, 0xBF, 0x91, 0xF3, 0x7B, 0x60, 0x32, 0xB6, 0x00, 0x80, 0xFF, 0x36, 0xDF, 0x03, 0x32, 0xFF, 0x7C, 0x27, 0x27, 0x53, 0x3F, 0x55, 0x0D, 0x42, 0xFF, 0x48, 0x27, 0x9D, 0xB0, 0x27, 0xA1, 0xA4, 0x27, 0x8D, 0x60, 0x24, 0x27, 0x88, 0x36, 0xCB, 0x30, 0x03, 0x00, 0x00, 0xBC, 0xAD, 0x20, 0x03, 0x24, 0x27, 0xAB, 0x88, 0x37, 0x73, 0x27, 0x94, 0xB0, 0x26, 0xE7, 0x02, 0x74, 0x0A, 0x00, 0x00, 0x78, 0x0B, 0x32, 0xDF, 0x57, 0xF9, 0x00, 0x03, 0x5B, 0x37, 0x32, 0x27, 0x6E, 0x26, 0xB1, 0x33, 0xB7, 0x50, 0x41, 0x83, 0x2F, 0x71, 0x02, 0xF2, 0xE3, 0x73, 0xDB, 0x01, 0x13, 0x07, 0x50, 0x5F, 0x33, 0x00, 0x80, 0x67, 0x77, 0xB8, 0x60, 0x67, 0x20, 0xAA, 0x43, 0xC7, 0x38, 0x63, 0xC7, 0x30, 0x6F, 0x93, 0x9F, 0x53, 0xA0, 0x24, 0x0A, 0xA0, 0x27, 0xA5, 0x80, 0xBE, 0x24, 0x39, 0x23, 0x16, 0x23, 0xA0, 0xC0, 0x48, 0x79, 0x06, 0x02, 0x00, 0x30, 0x37, 0x70, 0x23, 0x00, 0x33, 0x33, 0xB3, 0x3F, 0xFC, 0x2D, 0xEC, 0xBC, 0x8C, 0x70, 0x0B, 0x0A, 0xD7, 0x23, 0x20, 0x0B, 0x30, 0x2F, 0x80, 0x3F, 0xBC, 0x48, 0xA9, 0x07, 0x01, 0xD0, 0x2F, 0xF4, 0x2F, 0xB0, 0x6B, 0x39, 0x0C, 0x40, 0x9D, 0x6F, 0x1C, 0x30, 0x97, 0x61, 0xEF, 0xCC, 0x28, 0x45, 0x30, 0x9B, 0x70, 0xF3, 0x24, 0x87, 0xDC, 0xE4, 0xB9, 0x71, 0x5B, 0x50, 0xF1, 0x5B, 0x29, 0x39, 0xD4, 0x8B, 0x80, 0x41, 0x17, 0xCD, 0xCC, 0xCC, 0x20, 0xEB, 0x20, 0x34, 0x02, 0x00, 0x41, 0x67, 0x00, 0x14, 0xBB, 0xE6, 0x30, 0x7F, 0x30, 0x2F, 0x71, 0x73, 0x44, 0x73, 0xF5, 0x38, 0x01, 0xA0, 0x7F, 0xC1, 0xA3, 0x20, 0x7F, 0x3E, 0x02, 0xD0, 0x7F, 0x52, 0x65, 0x64, 0x01, 0x70, 0xFF, 0xC1, 0xEB, 0x85, 0x45, 0x43, 0xC2, 0xB7, 0x6D, 0xDB, 0x20, 0x7F, 0x8C, 0x25, 0x02, 0x35, 0x20, 0xC1, 0x00, 0xD1, 0x8B, 0xB6, 0x1B, 0x5C, 0xA4, 0x87, 0xB4, 0x41, 0x3B, 0x0B, 0x92, 0x24, 0xE9, 0xC0, 0x60, 0x8B, 0x31, 0x00, 0x32, 0xE7, 0x35, 0x33, 0xD7, 0xF2, 0xE7, 0x92, 0x53, 0xF0, 0x26, 0x82, 0x20, 0x25, 0x1B, 0x90, 0x0B, 0x50, 0x97, 0xFA, 0x34, 0xEF, 0x00, 0x50, 0x97, 0x96, 0x53, 0x30, 0x3B, 0x77, 0x04, 0xAA, 0xF1, 0x17, 0x32, 0xFF, 0x02, 0x13, 0x73, 0x32, 0xF7, 0x50, 0x8B, 0x00, 0x96, 0x7B, 0x33, 0x1B, 0x57, 0x78, 0x00, 0x31, 0x7F, 0x3B, 0x90, 0x9B, 0x57, 0x07, 0x54, 0x53, 0x2A, 0xEE, 0x47, 0x73, 0x4C, 0x37, 0x8B, 0x2B, 0xD9, 0x76, 0x94, 0x63, 0x8B, 0x3B, 0x87, 0x3B, 0xD1, 0x24, 0x4B, 0xD5, 0x00, 0x01, 0x97, 0xC0, 0x1E, 0x39, 0x8E, 0xE3, 0x2B, 0x39, 0x51, 0x5B, 0x5B, 0xFD, 0x01, 0x20, 0x23, 0x03, 0x81, 0xF7, 0x6B, 0x40, 0x41, 0x9E, 0x15, 0x8D, 0xBD, 0x31, 0xA3, 0x1A, 0x9A, 0x99, 0xB9, 0x2B, 0x7D, 0x2C, 0x5A, 0x04, 0x01, 0x10, 0x23, 0x01, 0xAA, 0x01, 0x20, 0x8F, 0x01, 0x01, 0x20, 0x8F, 0x01, 0x00, 0x10, 0x8F, 0xC1, 0x20, 0x8F, 0x3D, 0xD8, 0x60, 0x8F, 0x44, 0x5B, 0x01, 0x00, 0x10, 0x8F, 0x00, 0x00, 0x23, 0x50, 0x5F, 0x42, 0x20, 0x6C, 0x6B, 0x03, 0xE1, 0x63, 0x9A, 0x99, 0x19, 0xC0, 0x0E, 0x3F, 0x74, 0xDA, 0x00, 0xC1, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0xEA, 0x03, 0x81, 0x63, 0x00, 0x13, 0xBB, 0x00, 0x32, 0xC7, 0x58, 0x2E, 0x9D, 0x88, 0x66, 0x4F, 0xE8, 0xAB, 0x2E, 0xA9, 0x18, 0x2E, 0x95, 0x48, 0x2E, 0x99, 0x78, 0x62, 0xC7, 0xE3, 0xD3, 0xEF, 0x56, 0x3F, 0x60, 0x0B, 0x52, 0xD3, 0xF0, 0xC2, 0xD3, 0x01, 0xC0, 0x2F, 0x22, 0xDF, 0xD4, 0x33, 0x77, 0x40, 0x68, 0x03, 0x50, 0x0B, 0x52, 0xEB, 0xF0, 0xC2, 0xEB, 0x01, 0xB0, 0x2F, 0x32, 0xF7, 0xFF, 0x01, 0xB0, 0xBF, 0x33, 0x03, 0x01, 0xC0, 0x2F, 0x00, 0x10, 0xBF, 0x45, 0x73, 0x70, 0x0B, 0x53, 0x1B, 0x40, 0xBF, 0xFF, 0x83, 0x1B, 0x01, 0xB0, 0x2F, 0x63, 0x27, 0x03, 0xC1, 0xC3, 0x33, 0x27, 0x75, 0x97, 0x93, 0x33, 0x00, 0x91, 0xC3, 0xFF, 0x01, 0x00, 0x2F, 0x05, 0xE1, 0xC3, 0x00, 0xF0, 0xBF, 0xF1, 0xC3, 0x01, 0x00, 0x2F, 0x05, 0x01, 0xC3, 0x00, 0x16, 0xB7, 0x00, 0x36, 0x4F, 0xF5, 0x35, 0xCC, 0x33, 0x8B, 0x36, 0x53, 0x33, 0x8F, 0xA0, 0x69, 0xE3, 0xD0, 0x6D, 0xAB, 0xFF, 0xE6, 0xCF, 0x59, 0xC7, 0x26, 0x43, 0x00, 0x40, 0x17, 0x26, 0x37, 0xD6, 0xFF, 0x63, 0x57, 0x26, 0x2B, 0xFF, 0x00, 0x30, 0x17, 0x36, 0x1F, 0x00, 0x30, 0x5F, 0x36, 0x13, 0x00, 0x40, 0x17, 0x00, 0x10, 0x5F, 0x48, 0x6B, 0x35, 0xFB, 0xFF, 0x00, 0x30, 0x17, 0x65, 0xEF, 0x03, 0xC1, 0x03, 0x82, 0xC7, 0xE1, 0x03, 0x82, 0xDF, 0x02, 0xE1, 0x03, 0x73, 0x27, 0xF6, 0xF1, 0x03, 0x80, 0x17, 0x01, 0xE1, 0x03, 0x00, 0xFD, 0xDF, 0x54, 0xEC, 0xDF, 0x02, 0x7E, 0xDF, 0x04, 0xEA, 0x2F, 0xA4, 0x5F, 0x0D, 0xDC, 0xDF, 0x50, 0x2F, 0xCC, 0xB8, 0x2F, 0xD0, 0x20, 0xAA, 0x2F, 0xBC, 0xA0, 0x2F, 0xC0, 0x2C, 0x2C, 0xE3, 0xAC, 0x2C, 0xE7, 0x10, 0xA5, 0x2C, 0xDF, 0x74, 0x2C, 0xDF, 0xD8, 0x07, 0x2D, 0x17, 0x09, 0x2C, 0x31, 0xFD, 0x2C, 0xE3, 0x02, 0x9C, 0xDF, 0x3E, 0xCF, 0x00, 0xFC, 0xDF, 0x9E, 0xF3, 0x00, 0xBC, 0xDF, 0x7C, 0xEC, 0xDF, 0x7F, 0x2C, 0x6D, 0x5B, 0xDD, 0x4F, 0x4C, 0xE3, 0x8C, 0xD3, 0xD0, 0x17, 0x9C, 0xBB, 0x00, 0x30, 0x17, 0xFB, 0x00, 0x9F, 0xD3, 0x3F, 0xFD, 0x01, 0x1C, 0x8B, 0x00, 0x0D, 0xE7, 0xC3, 0xA3, 0xA0, 0x81, 0xF3, 0x00, 0x9F, 0xFB, 0xF6, 0x30, 0x23, 0x01, 0x1C, 0x73, 0x03, 0xD0, 0x67, 0x02, 0x7C, 0x5B, 0x70, 0x2B, 0xCB, 0x7C, 0x5B, 0x20, 0xFE, 0x3B, 0xDB, 0x00, 0xEB, 0xC3, 0x3E, 0x67, 0x7F, 0xD7, 0x5B, 0xCF, 0x00, 0xFC, 0x4F, 0x00, 0xDC, 0xDB, 0xF0, 0xFB, 0x2C, 0xCB, 0x80, 0x7F, 0x01, 0x2C, 0xDB, 0x30, 0x2F, 0x7F, 0xFB, 0xC8, 0x2F, 0x03, 0x7C, 0xDB, 0xFF, 0x5B, 0xE7, 0xAC, 0xDB, 0x00, 0x4C, 0x4F, 0x03, 0x3D, 0x67, 0x00, 0x1E, 0x67, 0xDD, 0x67, 0x04, 0x1C, 0x67, 0x41, 0xA3, 0xFF, 0x79, 0x93, 0x9D, 0x43, 0xCC, 0x67, 0x00, 0x60, 0x23, 0xCC, 0x67, 0x31, 0xEB, 0x89, 0x7B, 0x28, 0x2F, 0xFF, 0x00, 0x3C, 0x67, 0x00, 0x50, 0x23, 0xDC, 0x67, 0x00, 0x50, 0x8F, 0xDC, 0x67, 0x00, 0x60, 0x23, 0x00, 0x10, 0x8F, 0x79, 0x4B, 0xF3, 0x30, 0x8F, 0x00, 0x2C, 0x67, 0x00, 0x50, 0x23, 0x04, 0x1C, 0x67, 0x70, 0xC2, 0xA9, 0x33, 0x00, 0x81, 0x63, 0xFF, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0x03, 0x81, 0x63, 0x01, 0x5C, 0x67, 0x01, 0x9F, 0x2F, 0xFF, 0x43, 0xEB, 0x6F, 0x2F, 0x9F, 0x97, 0xDF, 0x2F, 0x00, 0x60, 0x23, 0xCF, 0x2F, 0x34, 0x33, 0x7F, 0x2F, 0xFF, 0x38, 0x2F, 0x00, 0x3F, 0x2F, 0x00, 0x50, 0x23, 0xDF, 0x2F, 0x00, 0x50, 0x8F, 0xDF, 0x2F, 0x00, 0x60, 0x23, 0x00, 0x10, 0x8F, 0xFF, 0x6F, 0x2F, 0x40, 0x8F, 0x00, 0x2F, 0x2F, 0x00, 0x50, 0x23, 0x01, 0x7C, 0x07, 0x01, 0xB1, 0x63, 0x9F, 0x2F, 0x00, 0x91, 0x63, 0xFF, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0x03, 0x81, 0x63, 0x01, 0x5B, 0xA7, 0x01, 0x95, 0x8F, 0xFF, 0x46, 0x27, 0x6F, 0x23, 0x9F, 0xDF, 0xD5, 0x8F, 0x00, 0x60, 0x23, 0xC5, 0x8F, 0x4F, 0xDF, 0x6F, 0x0B, 0xFF, 0x4F, 0xDF, 0x00, 0x25, 0x8F, 0x00, 0x50, 0x23, 0xD5, 0x8F, 0x00, 0x50, 0x8F, 0xD5, 0x8F, 0x00, 0x60, 0x23, 0x00, 0x10, 0x8F, 0xFF, 0x6E, 0xDB, 0x40, 0x8F, 0x00, 0x25, 0x8F, 0x00, 0x50, 0x23, 0x01, 0x7C, 0x07, 0x01, 0xB1, 0x63, 0x9E, 0xC3, 0x00, 0x91, 0x63, 0xFE, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0x03, 0x61, 0x63, 0x00, 0x7C, 0x5F, 0x4C, 0xF1, 0x2C, 0x5C, 0xBC, 0x5F, 0x3E, 0x51, 0x7C, 0x5F, 0x65, 0x00, 0x73, 0xCC, 0x5F, 0x8A, 0x3B, 0x9C, 0x47, 0x5F, 0x43, 0x00, 0x4C, 0x5F, 0xFC, 0x2E, 0xBB, 0x0F, 0xF5, 0x5B, 0x58, 0x4C, 0x5F, 0x3C, 0x82, 0x3B, 0xAB, 0xBC, 0x2F, 0xFF, 0xFC, 0x2F, 0xF8, 0x57, 0x3C, 0x2E, 0xDB, 0x7C, 0x2E, 0xDF, 0xBC, 0x2E, 0xE3, 0x00, 0x3C, 0x47, 0x3E, 0xC7, 0xCB, 0x5E, 0xFB, 0x00, 0x7A, 0x3B, 0x80, 0xBF, 0x9A, 0x3B, 0x60, 0x88, 0xC7, 0x00, 0x3C, 0x2B, 0xDD, 0x00, 0x70, 0x4B, 0x9F, 0x2B, 0xCA, 0x2A, 0xB7, 0x00, 0x9B, 0xCB, 0x01, 0x10, 0x3F, 0xF2, 0xA0, 0x3F, 0xF7, 0x00, 0x1B, 0xA3, 0x01, 0xD0, 0x3F, 0x00, 0x29, 0xEF, 0x01, 0x00, 0xBF, 0x8E, 0x2B, 0x77, 0x70, 0xFF, 0x00, 0x27, 0x67, 0xBB, 0x01, 0x00, 0xFF, 0x24, 0xF0, 0x3F, 0xDF, 0x83, 0x01, 0x01, 0x3F, 0x30, 0x00, 0x8E, 0xBB, 0x5E, 0xBF, 0x2A, 0x59, 0x54, 0x7E, 0xBF, 0xA8, 0x2E, 0xBC, 0x10, 0x2F, 0xFB, 0x6C, 0x19, 0x79, 0x74, 0x31, 0x3E, 0xD1, 0x4A, 0x9E, 0x00, 0xA0, 0x2D, 0xE7, 0x03, 0x70, 0x43, 0x74, 0x78, 0x6C, 0x31, 0x3F, 0xDF, 0x3F, 0xBF, 0x60, 0x04, 0x2F, 0xFF, 0x2D, 0x55, 0x74, 0x65, 0x6E, 0x64, 0x6F, 0x00, 0x5F, 0x31, 0x32, 0x38, 0x78, 0x36, 0x34, 0x2E, 0x05, 0x62, 0x63, 0x6C, 0x69, 0x6D, 0x2F, 0xFF, 0x6D, 0x2E, 0xFB, 0x70, 0x60, 0x62, 0x23, 0x30, 0x4B, 0x4D, 0x7F, 0x4C, 0x6F, 0x67, 0x6F, 0x8D, 0xAE, 0xE9, 0xFF, 0xFF, 0xFF, 0x30, 0x03, 0x00, 0x40, 0x02, 0x15, 0x5F, 0xE0, 0xF0, 0x30, 0x62, 0xAF, 0x72, 0x3E, 0x07, 0x5E, 0x0B, 0x70, 0x61, 0x6E, 0x31, 0x80, 0x3B, 0x4F, 0x01, 0x04, 0xFF, 0x00, 0x52, 0x6F, 0x6F, 0x07, 0x74, 0x50, 0x61, 0x6E, 0x65, 0x00, 0xB0, 0xDF, 0x00, 0x50, 0x47, 0x50, 0xD3, 0x0D, 0x70, 0x61, 0x73, 0x31, 0x3B, 0xA3, 0x70, 0x53, 0x03, 0x20, 0x53, 0x3D, 0x4E, 0x5F, 0x30, 0x55, 0x00, 0x0F, 0x96, 0x01, 0x20, 0x53, 0x4C, 0xD3, 0x42, 0x80, 0x53, 0x09, 0x69, 0x63, 0x31, 0x80, 0x3C, 0x0F, 0x07, 0xFF, 0x00, 0x41, 0x03, 0xF9, 0x7E, 0xE0, 0x2D, 0x5B, 0x82, 0x1F, 0x00, 0x20, 0xEF, 0x2F, 0x63, 0x80, 0x42, 0xF1, 0x2B, 0xE0, 0x71, 0x99, 0xCF, 0x23, 0xC1, 0x27, 0x80, 0x3F, 0x70, 0x61, 0x65, 0xC3, 0x60, 0xDB, 0x50, 0x07, 0x67, 0x72, 0x70, 0x31, 0x3C, 0x97, 0x31, 0x33, 0x0C, 0x47, 0x72, 0x6F, 0x75, 0x3C, 0x8F, 0x7F, 0xE7, 0x67, 0x72, 0xE3, 0x51, 0x07, 0x30, 0x23, 0x34, 0x57, 0x47, 0x5F, 0x41, 0xCF, 0xD3, 0x3F, 0xCF, 0xF1, 0xF1, 0x17, 0xF1, 0xD7, 0x30, 0x5F, 0x3F, 0xDF, 0x47, 0x5F, 0x42, 0xCF, 0x6D, 0xF9, 0x3F, 0xE7, 0x00, 0x90, 0x2B, 0xD4, 0x9F, 0x3F, 0xFB, 0xF1, 0x7F, 0x67, 0x72, 0x50, 0xC7, 0xAB, 0x01, 0x32, 0xBF, 0x3C, 0x22, 0xBC, 0x22, 0x00, 0x02, 0xBF, 0xC8, 0x82, 0xBF, 0x3D, 0x7F, 0x59, 0x07, 0x64, 0xBB, 0x2D, 0x2F, 0xFF, 0x2F, 0x08, 0x00, 0x4F, 0x34, 0xA1, 0xD1, 0x32, 0xF3, 0x2F, 0xFF, 0x78, 0x2F, 0xFB, 0x33, 0x64, 0x73, 0x62, 0xAD, 0xD5, 0x62, 0xD2, 0x80, 0x10, 0x31, 0xF0, 0x10, 0x32, 0xF0, 0x21, 0x33, 0x63, 0x05, 0x38, 0x4C, 0x54, 0x90, 0x3E, 0x30, 0x0B, 0x70, 0x39, 0x4C, 0x54, 0x4D, 0x38, 0x61, 0x73, 0x3C, 0xCC, 0x63, 0x2D, 0x33, 0x2B, 0xA8, 0x06, 0x00, 0x2A, 0x00, 0x0B, 0x2F, 0xFF, 0x38, 0x2F, 0xFF, 0x88, 0x2F, 0xFB, 0x08, 0xAA, 0x2F, 0xF4, 0x88, 0x2F, 0xF8, 0x08, 0x2F, 0xD4, 0x88, 0x2F, 0xD8, 0x4C, 0xA9, 0x2F, 0x10, 0xE8, 0x2F, 0x14, 0xAC, 0x23, 0x74, 0x48, 0x05, 0x2F, 0xD7, 0xDB, 0x20, 0x2F, 0x00, 0x35, 0x47, 0xAA, 0x53, 0x57, 0x00, 0x83, 0x53, 0x02, 0x00, 0xA3, 0x53, 0x00, 0x35, 0x57, 0xB6, 0x00, 0xB3, 0xA3, 0xD5, 0x20, 0xB3, 0x00, 0xB3, 0xA3, 0x40, 0x24, 0x20, 0x30, 0x03, 0x11, 0x86, 0x2F, 0xFB, 0x74, 0x06, 0x00, 0x04, 0x30, 0x03, 0x30, 0x0B, 0x65, 0x1E, 0x06, 0x00, 0x01, 0x30, 0x03, 0x30, 0x17, 0x31, 0x87, 0x5E, 0x03, 0x05, 0x9B, 0x2F, 0x47, 0x4F, 0x5F, 0x31, 0x32, 0x01, 0xB0, 0x7F, 0x01, 0x03, 0xE0, 0x7F, 0xD2, 0xB5, 0x07, 0x00, 0x00, 0x8C, 0x8C, 0x8C, 0x05, 0xA0, 0x7F, 0x00, 0x16, 0x97, 0x00, 0xF1, 0x7F, 0x7C, 0x03, 0x03, 0xC1, 0x7F, 0x00, 0x16, 0xD7, 0x45, 0xA7, 0x2F, 0xB4, 0x00, 0x25, 0xA7, 0x80, 0x3F, 0xB0, 0x23, 0x44, 0x04, 0x25, 0xA3, 0x30, 0x03, 0x06, 0x00, 0x06, 0x06, 0x0C, 0x73, 0x09, 0xED, 0xBE, 0x30, 0x03, 0x3F, 0xFB, 0x3A, 0x57, 0x37, 0xDE, 0x40, 0x30, 0x03, 0xE0, 0x13, 0xC0, 0x30, 0x03, 0x00, 0x75, 0xD3, 0x78, 0x54, 0x00, 0x10, 0x04, 0x00, 0x01, 0x10, 0x04, 0x10, 0x02, 0xA0, 0xA2, 0x37, 0x46, 0xF2, 0x37, 0x26, 0x06, 0x02, 0x05, 0x66, 0xF9, 0x23, 0x33, 0x00, 0x12, 0x43, 0x4D, 0x5F, 0x00, 0x35, 0xB6, 0x00, 0x36, 0x6A, 0x80, 0xEA, 0x23, 0x77, 0x61, 0x05, 0x26, 0x67, 0x30, 0x03, 0x30, 0x8E, 0xE3, 0xBE, 0x30, 0x03, 0xF7, 0xB0, 0xBF, 0xE0, 0x13, 0xC0, 0xBF, 0x50, 0xA7, 0x00, 0x00, 0xC0, 0xA7, 0x00, 0x21, 0x5F, 0xCF, 0x5F, 0x86, 0x01, 0xB1, 0x5F, 0x2F, 0xA1, 0xBD, 0xBF, 0x30, 0x03, 0x3F, 0xF7, 0xCE, 0x1B, 0x95, 0x17, 0x41, 0x30, 0x03, 0xE0, 0x13, 0xC1, 0x30, 0x03, 0x05, 0x21, 0x5F, 0xC3, 0x00, 0x00, 0xC3, 0x01, 0x31, 0x5F, 0x61, 0x0B, 0xB6, 0xBF, 0x30, 0x03, 0xB0, 0xBF, 0xFF, 0xE0, 0x13, 0xC0, 0xBF, 0x02, 0x61, 0x5F, 0xCD, 0xF7, 0x01, 0xB2, 0xBF, 0x3F, 0xF7, 0x50, 0x03, 0x5D, 0xA7, 0xFF, 0x50, 0x03, 0xC0, 0x13, 0x4F, 0xF7, 0x05, 0x22, 0xBF, 0x00, 0x00, 0xC3, 0x01, 0x32, 0xBF, 0x3F, 0xE3, 0x3F, 0xE7, 0xFF, 0xB0, 0xBF, 0xE0, 0x13, 0xC0, 0xBF, 0x01, 0xF2, 0xBF, 0x03, 0x59, 0x73, 0x57, 0x87, 0x00, 0x59, 0x73, 0x00, 0x1C, 0x63, 0xFA, 0x99, 0x1F, 0x40, 0x03, 0x00, 0x79, 0x1F, 0x3F, 0x93, 0xC9, 0x73, 0xA0, 0x4E, 0xC7, 0xF5, 0xC7, 0x00, 0x84, 0xD3, 0x70, 0x53, 0x46, 0x31, 0x32, 0x00, 0x63, 0x2F, 0x58, 0x2F, 0xFA, 0x9F, 0x41, 0x05, 0x4F, 0xF1, 0x00, 0x00, 0xCD, 0xCC, 0x4C, 0x28, 0x36, 0x3F, 0x80, 0x3F, 0x50, 0x07, 0x40, 0x0F, 0x4A, 0x9B, 0x50, 0x07, 0x9F, 0xEC, 0xE0, 0x0B, 0xFB, 0x40, 0x03, 0x00, 0x0A, 0x1B, 0x2A, 0xC3, 0x00, 0xA4, 0xB7, 0x60, 0xFB, 0x20, 0x01, 0xC0, 0xA7, 0x27, 0x62, 0xEC, 0x01, 0x00, 0xA7, 0x8A, 0x1B, 0x81, 0x2F, 0x91, 0x00, 0x84, 0xA3, 0x71, 0x83, 0x10, 0xF4, 0x5D, 0xBF, 0x01, 0xC1, 0x2F, 0x07, 0x04, 0xD1, 0x2F, 0x00, 0x80, 0xA7, 0x01, 0xF1, 0x2F, 0x08, 0x02, 0x41, 0x2F, 0xF7, 0x00, 0x5D, 0x8B, 0xE1, 0xB7, 0xEB, 0xD7, 0x00, 0xD2, 0x5F, 0x09, 0x04, 0xD2, 0x5F, 0x00, 0xB0, 0xA7, 0x01, 0xC3, 0x07, 0x7B, 0x0A, 0x01, 0xE2, 0x5F, 0x92, 0xE7, 0x00, 0x1F, 0xFB, 0x5F, 0xC7, 0xF8, 0x25, 0x6F, 0x3D, 0x07, 0x5A, 0xA0, 0x00, 0x68, 0x1F, 0x10, 0x43, 0xE3, 0x00, 0x5D, 0x03, 0x50, 0x43, 0x83, 0x00, 0x3F, 0x00, 0x44, 0x6D, 0x03, 0x30, 0x0F, 0x3E, 0x2B, 0x30, 0x0F, 0x2D, 0x03, 0x6D, 0x83, 0x3D, 0x03, 0x08, 0x6D, 0x83, 0x00, 0xC3, 0x67, 0x00, 0x70, 0x7F, 0x4D, 0x83, 0x41, 0xFE, 0xAF, 0x7F, 0x01, 0x01, 0x4D, 0x83, 0x00, 0x3E, 0x0B, 0x00, 0x1A, 0xEB, 0x01, 0x94, 0xEB, 0x00, 0x10, 0x87, 0x5F, 0xE9, 0x00, 0xEE, 0x0B, 0xBB, 0x7E, 0x8B, 0x01, 0x50, 0x7F, 0xFA, 0xEB, 0x02, 0xB0, 0x7F, 0x03, 0x8E, 0x8B, 0x9E, 0x7B, 0xDF, 0xFE, 0x9B, 0x00, 0x02, 0x0F, 0x03, 0x3F, 0x13, 0x00, 0x1A, 0xF3, 0x01, 0x91, 0x8F, 0x00, 0x12, 0x0F, 0x2A, 0x3A, 0xAF, 0x04, 0x8F, 0x13, 0xDC, 0x00, 0x2F, 0x13, 0x0C, 0x4F, 0x13, 0xD6, 0xB7, 0xFD, 0x97, 0xFD, 0x57, 0xFF, 0xFC, 0xE7, 0xFC, 0x77, 0xFC, 0x07, 0xFB, 0x97, 0xFA, 0xE3, 0xFA, 0x57, 0xF9, 0xA3, 0xF9, 0x17, 0xDD, 0xF8, 0x63, 0x3F, 0xEF, 0xCC, 0x00, 0x2F, 0xB3, 0x3E, 0x8F, 0x0A, 0x30, 0xCB, 0x2C, 0x41, 0xA7, 0x73, 0x43, 0xCF, 0x1B, 0x37, 0x0D, 0xF8, 0x5F, 0x67, 0x72, 0x56, 0xFF, 0x03, 0x40, 0x02, 0x04, 0x40, 0x00, 0x78, 0x80, 0x80, 0x34, 0x8F, 0x00, 0x00, 0x60, 0x0A, 0x2B, 0xA1, 0x20, 0x0B, 0xEF, 0x80, 0x80, 0xEF, 0xEF, 0x00, 0xFF, 0xF8, 0x0B, 0xBF, 0x70, 0x01, 0xFF, 0xF6, 0x82, 0x8F, 0xA5, 0x20, 0x00, 0x88, 0x40, 0x30, 0x50, 0x27, 0x1C, 0x0F, 0xCF, 0x00, 0x01, 0x30, 0x20, 0x0B, 0x30, 0x03, 0x38, 0x56, 0x4F, 0x99, 0x01, 0x87, 0x00, 0x05, 0xFD, 0xFC, 0x0B, 0x0A, 0x3F, 0xA5, 0x86, 0x3F, 0xA9, 0xFC, 0xFC, 0x0A, 0x0A, 0x30, 0x03, 0x2F, 0xE5, 0x83, 0x09, 0x00, 0x00, 0xF7, 0xF7, 0x3F, 0x30, 0xBF, 0xFF, 0x31, 0x9A, 0xC0, 0x20, 0x0B, 0x20, 0x0F, 0xFF, 0x9F, 0xCF, 0xFF, 0x1F, 0x2F, 0x20, 0xF6, 0x60, 0xAF, 0xD3, 0x81, 0x00, 0x00, 0xF3, 0xF3, 0x49, 0x01, 0x22, 0xD0, 0xCF, 0xFF, 0x30, 0x05, 0xF3, 0xF3, 0x40, 0x03, 0x04, 0x28, 0x00, 0x00, 0x5F, 0x5F, 0x40, 0x5F, 0x88, 0xFE, 0x1C, 0xCA, 0xFF, 0xCC, 0x30, 0x0B, 0x40, 0x0F, 0x7F, 0xEC, 0x88, 0x00, 0x19, 0x88, 0xFF, 0xCC, 0x2F, 0xEC, 0x30, 0x07, 0xCF, 0xFF, 0x22, 0x0E, 0x2E, 0xFC, 0xFC, 0x30, 0x7D, 0x0C, 0x22, 0xE0, 0x30, 0x03, 0x20, 0x1F, 0x06, 0x00, 0xFF, 0xCC, 0x0D, 0x0A, 0x00, 0x30, 0x00, 0x88, 0x3E, 0x60, 0x60, 0x50, 0xE7, 0x3F, 0xFD, 0x30, 0x0B, 0x40, 0x0F, 0x30, 0x3F, 0xCD, 0xC8, 0x20, 0x37, 0x50, 0x47, 0xCC, 0x02, 0x2D, 0xC7, 0x34, 0xFF, 0x33, 0xB5, 0x41, 0x0F, 0x33, 0x30, 0x07, 0x40, 0x3F, 0x0E, 0x30, 0xC7, 0x84, 0x25, 0xEB, 0x7C, 0xF8, 0x4F, 0xF3, 0x2F, 0xBF, 0x50, 0x0B, 0x20, 0x0F, 0x2F, 0x88, 0xAF, 0xFF, 0x60, 0x00, 0x30, 0xE7, 0x5F, 0xF7, 0x8E, 0xBF, 0xFF, 0x0E, 0x1E, 0x28, 0xF7, 0x70, 0x32, 0x84, 0xBF, 0x40, 0xC7, 0x00, 0x82, 0x00, 0x27, 0x00, 0xF4, 0x40, 0xC7, 0x4F, 0x4F, 0x3F, 0xF1, 0x50, 0xD7, 0x30, 0x0B, 0x80, 0x40, 0x0F, 0x80, 0x00, 0x88, 0xF1, 0xE1, 0xFF, 0xEF, 0x86, 0x70, 0x7F, 0xE1, 0xE1, 0x7F, 0x7F, 0x30, 0x03, 0xE0, 0xDF, 0xDC, 0x01, 0x00, 0x15, 0x00, 0x00, 0xEF, 0xFF, 0x05, 0x40, 0x41, 0x89, 0x3F, 0xFA, 0xD3, 0x40, 0xDF, 0x2E, 0xDE, 0xFD, 0xFA, 0x00, 0x0E, 0x2F, 0x9C, 0x2F, 0xD5, 0x07, 0x09, 0x01, 0xAA, 0xDD, 0x21, 0xEB, 0x31, 0xEF, 0x01, 0x01, 0x60, 0x60, 0x25, 0x5F, 0x40, 0x0F, 0xFF, 0x70, 0x00, 0xDE, 0x01, 0xC0, 0x30, 0x0B, 0x39, 0x89, 0xFF, 0xF6, 0x1C, 0xCF, 0x50, 0x00, 0x01, 0xFF, 0xF5, 0x30, 0x31, 0xFF, 0xFF, 0x5C, 0x46, 0xB7, 0x40, 0x50, 0x5F, 0xDF, 0xF5, 0xFF, 0xFF, 0x40, 0x00, 0xEE, 0x70, 0x10, 0xF1, 0xEF, 0x41, 0xFF, 0x2F, 0xFF, 0xFC, 0xFD, 0x0A, 0x0B, 0x30, 0xEB, 0x10, 0x30, 0x88, 0x51, 0xEF, 0x2F, 0x2F, 0x00, 0x00, 0xCA, 0x30, 0x03, 0x51, 0xFF, 0xE6, 0x10, 0x30, 0x0F, 0x2E, 0x2F, 0xFF, 0xF5, 0x40, 0x50, 0x30, 0xC7, 0xF5, 0x40, 0x02, 0x1D, 0xF3, 0xF2, 0x68, 0xDF, 0x20, 0x54, 0x7F, 0xC3, 0xF4, 0x2F, 0xB9, 0x00, 0x00, 0xD4, 0xEE, 0x41, 0xFB, 0xB1, 0xEF, 0x32, 0x0B, 0x4E, 0xB6, 0xBA, 0xF1, 0xEF, 0x20, 0x79, 0x00, 0x1E, 0x00, 0xEB, 0x10, 0x31, 0xFF, 0x34, 0x07, 0x00, 0x01, 0xEF, 0xB1, 0xFF, 0x00, 0x03, 0xEE, 0x11, 0xFF, 0x35, 0xFF, 0x33, 0x30, 0xF7, 0x21, 0xF2, 0x40, 0x33, 0x3F, 0xFF, 0x57, 0xFF, 0x55, 0xFF, 0xEE, 0x11, 0x16, 0xEE, 0x11, 0x55, 0x60, 0x07, 0x06, 0x87, 0x26, 0x51, 0xEF, 0x55, 0x06, 0xFF, 0x04, 0x0D, 0xEE, 0x11, 0x34, 0x61, 0x32, 0x0B, 0xE7, 0x04, 0x10, 0x1E, 0x1E, 0x00, 0x00, 0x30, 0x03, 0xF6, 0x60, 0x40, 0xCF, 0x2F, 0x0E, 0xF6, 0x50, 0x1E, 0x1F, 0x00, 0x00, 0x41, 0x1D, 0xAF, 0xC4, 0x01, 0x1C, 0xF3, 0xF3, 0xCF, 0x21, 0x2C, 0x97, 0x71, 0xEF, 0xF5, 0x50, 0x37, 0xFB, 0xE4, 0x42, 0x0B, 0x30, 0xC7, 0x61, 0xEF, 0x41, 0x6F, 0x7F, 0xF7, 0xE1, 0xF1, 0xAF, 0xFF, 0xD1, 0x20, 0x97, 0xC1, 0x70, 0x7F, 0x9F, 0x73, 0xF9, 0xFB, 0x10, 0x90, 0xFE, 0x20, 0x9D, 0x40, 0x65, 0x30, 0x9F, 0x01, 0xFB, 0xFF, 0x9F, 0x0B, 0x7C, 0xD8, 0x33, 0xB3, 0x2C, 0x8C, 0x06, 0x5B, 0xDA, 0x00, 0x4C, 0xD2, 0x43, 0x4C, 0x49, 0x08, 0x4D, 0xFF, 0xFE, 0x14, 0x2F, 0xFA, 0x02, 0x02, 0x28, 0xC1, 0x29, 0xF7, 0x3B, 0x5D, 0x69, 0x6D, 0x61, 0x67, 0x10, 0x4C, 0x9C, 0x18, 0x10, 0x00, 0x0D, 0x62, 0x33, 0x06, 0xD0, 0x01, 0x20, 0xA0, 0x00, 0x54, 0x71, 0x23, 0xDF, 0xFF, 0x33, 0xBF, 0xC0, 0x2E, 0xCB, 0xC0, 0xC0, 0x07, 0xAF, 0x9F, 0x00, 0x00, 0x9F, 0x20, 0x03, 0x73, 0x97, 0x80, 0x07, 0x81, 0xFF, 0xC0, 0x78, 0x00, 0x02, 0xFF, 0xFC, 0x3E, 0x4F, 0x9B, 0x87, 0x3F, 0xEE, 0x90, 0x90, 0xDF, 0xDF, 0x30, 0x03, 0x01, 0x9D, 0xDF, 0x50, 0x6F, 0xCA, 0x30, 0x6B, 0x40, 0x6F, 0x00, 0xB0, 0x44, 0x93, 0xDF, 0x22, 0x07, 0xD7, 0x3E, 0x00, 0xEE, 0x00, 0x0E, 0xCE, 0x42, 0x17, 0x20, 0x17, 0x70, 0x07, 0x40, 0x6F, 0x80, 0x81, 0x90, 0x6F, 0xC5, 0xFF, 0xCF, 0x7F, 0xDE, 0x00, 0x95, 0x9D, 0xEE, 0xC1, 0x7F, 0x63, 0x53, 0x71, 0x7F, 0x20, 0x71, 0x7F, 0xC2, 0xCF, 0x06, 0xB1, 0x8B, 0x50, 0xB0, 0xA8, 0x42, 0x70, 0x28, 0x4E, 0x2E, 0x06, 0x10, 0x00, 0x43, 0xFD, 0x89, 0x3A, 0xAF, 0x76, 0x00, 0x98, 0x6F, 0xC8, 0xCE, 0x47, 0x2D, 0xA3, 0x08, 0xFF, 0x7A, 0xFF, 0x45, 0x4F, 0xFE, 0xAA, 0x00, 0xBB, 0xA2, 0x4A, 0xCF, 0xBB, 0x50, 0x07, 0xFF, 0x23, 0xEF, 0x42, 0xB3, 0xFF, 0x11, 0x21, 0xFF, 0x53, 0x4F, 0xFF, 0x9A, 0x00, 0x68, 0x4A, 0xEF, 0x41, 0x24, 0x25, 0x1B, 0xFF, 0xAD, 0xFF, 0xFF, 0xC8, 0x3A, 0xFB, 0x68, 0xB3, 0x20, 0x0B, 0x2E, 0xA1, 0xFA, 0x56, 0x77, 0x27, 0xFF, 0x00, 0x7E, 0x4B, 0x85, 0x3F, 0x7B, 0xA7, 0x26, 0x8B, 0x2E, 0x0D, 0xB3, 0xC2, 0x07, 0xC0, 0x0A, 0x21, 0x1C, 0xF6, 0x22, 0xFF, 0x26, 0xC5, 0x86, 0x4F, 0x7F, 0xFD, 0x22, 0xFF, 0x46, 0x32, 0x4F, 0x7A, 0x43, 0xFF, 0x97, 0x6B, 0xE7, 0x37, 0x3B, 0x10, 0x03, 0xE7, 0xF2, 0xF4, 0xFF, 0xFF, 0xFC, 0x2F, 0x94, 0x30, 0x03, 0xA0, 0x9F, 0x9B, 0xDF, 0xAF, 0xA6, 0x0C, 0x09, 0xFF, 0x4F, 0x02, 0x00, 0x00, 0xFF, 0xAD, 0xBF, 0x04, 0x28, 0xFF, 0x00, 0x22, 0x6C, 0x03, 0x07, 0xE0, 0xF8, 0xD6, 0x00, 0xDD, 0x00, 0x48, 0x71, 0xDD, 0xD0, 0x26, 0x03, 0x61, 0xEF, 0x54, 0x00, 0x3D, 0x1D, 0xFF, 0xB8, 0xFF, 0xFE, 0x12, 0x00, 0x00, 0x51, 0x41, 0xEF, 0xFD, 0xA0, 0x97, 0x7F, 0x10, 0x06, 0x00, 0xFE, 0xFC, 0x10, 0xA0, 0x23, 0xF1, 0x6F, 0xFF, 0x2C, 0x01, 0xEF, 0x00, 0x03, 0xFF, 0xFF, 0x1E, 0x8F, 0xA1, 0x1B, 0x50, 0xEF, 0x21, 0x1F, 0xAF, 0x05, 0x94, 0x99, 0xA1, 0xF2, 0x00, 0x00, 0x70, 0xF2, 0x20, 0x03, 0x85, 0x89, 0x40, 0xD7, 0x37, 0xFF, 0x01, 0xBE, 0x88, 0x4D, 0xAF, 0x58, 0x00, 0x23, 0x4F, 0x7B, 0x64, 0xFF, 0xA7, 0x8B, 0x47, 0xE7, 0xDC, 0xFF, 0xED, 0x79, 0xA0, 0xDE, 0x28, 0x80, 0x30, 0xD2, 0x22, 0xCC, 0xFF, 0x50, 0xCF, 0x21, 0x00, 0x32, 0x42, 0xDF, 0x33, 0x47, 0x00, 0x26, 0x52, 0x73, 0x30, 0xFB, 0x3F, 0xB3, 0x40, 0x04, 0x63, 0x3F, 0x4C, 0x12, 0x38, 0x27, 0x7A, 0xEF, 0x35, 0x94, 0x72, 0xEF, 0x8E, 0xFF, 0x0B, 0xFF, 0x2F, 0x05, 0x4D, 0x2F, 0xCA, 0x6B, 0x03, 0xE4, 0x0C, 0x00, 0xB5, 0xFF, 0x74, 0x40, 0x29, 0xD4, 0x07, 0x55, 0xFF, 0x08, 0xC0, 0x7F, 0x91, 0x4A, 0x8B, 0x99, 0x00, 0x7E, 0x99, 0x5F, 0xB7, 0x5A, 0x97, 0x8F, 0xC7, 0x70, 0x17, 0x60, 0x1F, 0x8F, 0xE7, 0x56, 0x1B, 0xFF, 0x55, 0x01, 0x37, 0x97, 0x90, 0x1F, 0x78, 0x4F, 0xFF, 0x27, 0xC0, 0x9B, 0x4A, 0x27, 0x97, 0xFF, 0x2A, 0xA7, 0x27, 0x85, 0x35, 0x26, 0xBF, 0x24, 0x07, 0x88, 0x3F, 0xFF, 0x8B, 0xFF, 0x03, 0x44, 0x10, 0xC6, 0x00, 0xFF, 0x68, 0xD4, 0x80, 0x5F, 0x3F, 0xF0, 0x17, 0x9F, 0xF5, 0xEF, 0xFF, 0x07, 0x66, 0xCF, 0x45, 0x6F, 0x2B, 0x77, 0x3E, 0xEF, 0x3B, 0x7D, 0xAF, 0xF5, 0x30, 0x22, 0x20, 0xFB, 0x5F, 0x87, 0xF3, 0xF9, 0xF8, 0x90, 0x3F, 0x31, 0x4C, 0xB7, 0x22, 0x97, 0x00, 0x75, 0x85, 0xBF, 0x2F, 0xFF, 0xAF, 0x0D, 0x08, 0xFF, 0x9E, 0xFF, 0x45, 0x4F, 0x79, 0xA9, 0x00, 0x9A, 0xA2, 0x45, 0xBF, 0x89, 0x55, 0xA7, 0xFF, 0x22, 0xFF, 0x3E, 0x9F, 0x00, 0x0A, 0xFF, 0x75, 0xFF, 0xDA, 0x4F, 0xE3, 0x23, 0x35, 0xB7, 0x5E, 0x83, 0x8A, 0x8F, 0xFF, 0xFF, 0x7F, 0x8F, 0x52, 0x23, 0x0C, 0x0D, 0x92, 0x31, 0xEF, 0xE1, 0xEF, 0xE1, 0xFF, 0x7F, 0xC7, 0x02, 0x2D, 0x07, 0x30, 0x03, 0xF0, 0x0F, 0x01, 0x1D, 0xA6, 0x83, 0x45, 0x3E, 0x00, 0xFB, 0xB0, 0xFF, 0xFF, 0x25, 0x13, 0x4C, 0x5F, 0x9D, 0x5F, 0xFB, 0xF2, 0xD0, 0x28, 0x8B, 0x25, 0x31, 0x77, 0x11, 0x0D, 0xA5, 0x1B, 0xC1, 0x96, 0x44, 0x2D, 0x69, 0xFB, 0x01, 0x07, 0xF8, 0xF2, 0x86, 0x45, 0x04, 0x0E, 0x50, 0x00, 0x2F, 0x3F, 0x2C, 0x87, 0xE5, 0xFF, 0x09, 0xFF, 0x20, 0x00, 0xFA, 0x2D, 0xB1, 0x0D, 0x6F, 0x76, 0x87, 0x0E, 0x18, 0xEF, 0x00, 0x38, 0x77, 0x77, 0xC2, 0x5F, 0xAE, 0x4B, 0x6B, 0x1E, 0xFF, 0x01, 0xAF, 0x47, 0xCF, 0x4C, 0x6F, 0x26, 0x89, 0x00, 0x3E, 0x67, 0x3A, 0xE5, 0x0D, 0xB4, 0x2F, 0x04, 0xF1, 0xFF, 0x7F, 0xEB, 0xA0, 0xB0, 0x2C, 0x0D, 0xF4, 0x79, 0x7C, 0x0E, 0x00, 0x60, 0xFB, 0xFF, 0x28, 0x32, 0x00, 0xB0, 0x01, 0x24, 0x07, 0x4F, 0x3C, 0x08, 0x2F, 0x2C, 0x6F, 0x2E, 0xDD, 0xBD, 0xFE, 0xDB, 0x59, 0x00, 0xD8, 0xAD, 0x5E, 0x97, 0xA5, 0x37, 0x87, 0x61, 0x00, 0x17, 0x9F, 0x38, 0x93, 0x40, 0x96, 0x9E, 0xA5, 0x7D, 0xDF, 0xFE, 0x28, 0xAF, 0xD0, 0xE1, 0x39, 0xF1, 0x1A, 0x27, 0x87, 0xD8, 0x2F, 0xF7, 0x2F, 0xE3, 0x3F, 0x2B, 0x55, 0x98, 0xBE, 0x04, 0x07, 0xFF, 0x34, 0xFF, 0x08, 0x4F, 0x09, 0x0E, 0x13, 0xFF, 0x20, 0x4A, 0xBF, 0x22, 0x00, 0x47, 0x22, 0xC3, 0xEF, 0xDE, 0xFF, 0xDD, 0x55, 0x42, 0x60, 0x17, 0x30, 0x1F, 0x80, 0x49, 0x23, 0xFF, 0xED, 0xFF, 0x00, 0x31, 0x00, 0x95, 0xC9, 0x7A, 0xDB, 0x60, 0x37, 0xEE, 0x12, 0x2F, 0x61, 0x50, 0xFD, 0xDA, 0x11, 0x09, 0xFF, 0xBD, 0xFF, 0x69, 0x45, 0xE7, 0x14, 0x6B, 0x9B, 0x0F, 0x0D, 0x8E, 0x5E, 0x01, 0x9F, 0x6C, 0x52, 0x00, 0x1C, 0x2A, 0x35, 0x2E, 0xEF, 0x89, 0x2F, 0x03, 0xAD, 0x00, 0x47, 0x5A, 0x6F, 0xFD, 0x74, 0x4F, 0x9F, 0x1E, 0xB9, 0xFF, 0xDC, 0x4F, 0xFF, 0x28, 0x6C, 0x2B, 0xB2, 0x4F, 0x57, 0xBB, 0x6A, 0xFF, 0x2B, 0xAA, 0x2D, 0x64, 0x10, 0x60, 0xB7, 0x32, 0x35, 0xDC, 0x10, 0x15, 0x00, 0xB4, 0xEC, 0x2F, 0xD7, 0xF9, 0x7B, 0x78, 0xEF, 0x68, 0x9F, 0x10, 0x8B, 0xFF, 0x25, 0xAB, 0x8F, 0x6D, 0xFF, 0x8F, 0x02, 0x5F, 0x00, 0x3F, 0xCD, 0x6C, 0x01, 0xEC, 0xAC, 0xCE, 0x7F, 0x2E, 0xAB, 0xDE, 0x7F, 0x68, 0x7F, 0xC0, 0x9D, 0x2E, 0x04, 0x0E, 0x88, 0xFF, 0xEF, 0xEF, 0x8A, 0xAF, 0x8E, 0x00, 0x47, 0x24, 0xDD, 0x78, 0xDD, 0x77, 0x33, 0x11, 0x01, 0x33, 0x11, 0x8D, 0x7D, 0x13, 0x13, 0x7D, 0x20, 0x03, 0xBF, 0x8A, 0xBF, 0x77, 0x50, 0x17, 0x70, 0x07, 0xFF, 0x49, 0x30, 0x2B, 0xB0, 0x2F, 0xF0, 0x0F, 0xB7, 0x01, 0xB9, 0x7F, 0xA8, 0x6D, 0xEA, 0x7F, 0x7F, 0x10, 0x6F, 0x7F, 0x27, 0xB0, 0x04, 0xA1, 0x00, 0xA0, 0x0D, 0xB0, 0x01, 0x02, 0x60, 0xED, 0x61, 0xFF, 0x2C, 0xFF, 0xBE, 0x35, 0xFF, 0xF0, 0x3E, 0xB7, 0x00, 0xC0, 0xFF, 0x19, 0x00, 0x21, 0x1D, 0x01, 0x28, 0xFA, 0x18, 0xCC, 0xFF, 0x3A, 0x3B, 0x92, 0x40, 0x3F, 0x17, 0xFF, 0x6B, 0x8D, 0x27, 0x4C, 0x84, 0xFF, 0xE9, 0xBD, 0xB9, 0x3C, 0xB8, 0xFD, 0x23, 0x34, 0xE2, 0x30, 0x62, 0x4C, 0xDA, 0x40, 0x13, 0xF7, 0xFF, 0xF1, 0x20, 0x03, 0xEF, 0x08, 0xFF, 0xE8, 0xFF, 0xE0, 0x20, 0x03, 0xE1, 0xFF, 0xD9, 0x38, 0xFF, 0xD3, 0x50, 0x95, 0x2E, 0xE1, 0x21, 0x87, 0x57, 0xFF, 0x86, 0x34, 0xFF, 0xD1, 0x93, 0x69, 0x30, 0x41, 0xFA, 0x31, 0x9F, 0xAC, 0xFF, 0x44, 0xC7, 0x41, 0xA5, 0xD9, 0xFF, 0xE4, 0x50, 0x5B, 0xF6, 0xFF, 0x41, 0xF2, 0x20, 0x5D, 0xFB, 0xFF, 0xEE, 0xFF, 0xEA, 0x2F, 0x23, 0x54, 0xF5, 0x20, 0x05, 0xE4, 0x23, 0x97, 0xEA, 0x2E, 0x2E, 0xDA, 0xFF, 0x10, 0xDB, 0xFF, 0xD5, 0x2C, 0x6E, 0xC6, 0xFF, 0xD0, 0xFF, 0x05, 0xCB, 0xFF, 0xC1, 0xFF, 0xBC, 0x27, 0xE7, 0xE1, 0x20, 0x11, 0x41, 0xD2, 0x24, 0x7A, 0xDA, 0xFF, 0xCD, 0xFF, 0xCA, 0x20, 0x19, 0x04, 0xC1, 0xFF, 0xB7, 0xFF, 0xB3, 0x20, 0xFE, 0xBA, 0xFF, 0x14, 0xAF, 0xFF, 0xAB, 0x05, 0xD1, 0xFF, 0x5F, 0x62, 0x6D, 0x03, 0xFF, 0x51, 0x29, 0x20, 0xC2, 0xC2, 0xE1, 0x7F, 0x05, 0xFF, 0x9F, 0x22, 0x8D, 0x5B, 0x07, 0x21, 0x61, 0xA7, 0x20, 0x9A, 0x5F, 0xE9, 0x8A, 0xD9, 0x48, 0x38, 0x99, 0x50, 0xFE, 0x41, 0x01, 0xF7, 0x25, 0x34, 0xEA, 0xFF, 0xE0, 0x8D, 0xA2, 0xD1, 0x73, 0xF6, 0x80, 0x27, 0xF7, 0xFF, 0xEB, 0x25, 0x56, 0xE0, 0xA8, 0x21, 0x1D, 0xE9, 0x21, 0x25, 0xDE, 0x2F, 0x4A, 0xD4, 0xFF, 0xD3, 0x28, 0xFF, 0xC9, 0x2F, 0x52, 0xD3, 0x2B, 0x3D, 0xC9, 0xFF, 0xC8, 0xA8, 0x25, 0x49, 0xBD, 0x21, 0x07, 0xFC, 0x27, 0x46, 0xF0, 0xFF, 0xE6, 0xA2, 0x20, 0x2D, 0xE2, 0x25, 0x9E, 0xD5, 0xFF, 0xE3, 0x21, 0x95, 0xD6, 0xAA, 0x2D, 0xB0, 0xD0, 0x20, 0x21, 0xC3, 0x25, 0x10, 0xDA, 0x21, 0x3B, 0xCD, 0x28, 0xFF, 0xC5, 0x21, 0x4D, 0xC4, 0x25, 0x7B, 0xB6, 0xFF, 0xBF, 0x80, 0x21, 0x3D, 0xB2, 0xFF, 0xAB, 0xFF, 0xB0, 0xFF, 0xA9, 0x0A, 0xFF, 0xA3, 0xFF, 0x9C, 0x21, 0x51, 0xC0, 0x22, 0x4A, 0xB5, 0xA8, 0x21, 0x53, 0xAE, 0x21, 0xA8, 0xA2, 0x21, 0x59, 0xAA, 0xFF, 0xA8, 0xA0, 0x20, 0xC8, 0xA0, 0x2F, 0xE0, 0x95, 0xFF, 0x8C, 0xFF, 0xA6, 0x80, 0x2B, 0x49, 0x9A, 0xFF, 0x92, 0xFF, 0x96, 0xFF, 0x8F, 0xA8, 0x25, 0x33, 0x84, 0x20, 0x05, 0x87, 0x22, 0x2C, 0x7C, 0xFF, 0x7F, 0x2A, 0xFF, 0x79, 0x2B, 0x43, 0x6E, 0x22, 0x86, 0xB8, 0x20, 0x4B, 0xAA, 0x8C, 0x20, 0x53, 0xAD, 0xFF, 0xA4, 0x21, 0x00, 0x30, 0x53, 0x96, 0xFF, 0x54, 0x90, 0x2B, 0xFF, 0x92, 0x20, 0xFC, 0x85, 0x20, 0x4B, 0xA4, 0xFF, 0x41, 0x9B, 0x20, 0x3D, 0xA0, 0xFF, 0x9D, 0xFF, 0x93, 0x20, 0x17, 0x04, 0x8D, 0xFF, 0x89, 0xFF, 0x80, 0x20, 0x3F, 0x86, 0xFF, 0x50, 0x83, 0x20, 0x41, 0x76, 0x20, 0x0D, 0x83, 0xFF, 0x7D, 0xFF, 0x14, 0x77, 0xFF, 0x7E, 0x20, 0x4F, 0x72, 0x25, 0x87, 0x72, 0xFF, 0x04, 0x6C, 0xFF, 0x67, 0xFF, 0x62, 0x40, 0x03, 0x5C, 0xFF, 0x00, 0x58, 0xFF, 0x74, 0xFF, 0x70, 0xFF, 0x69, 0xFF, 0x50, 0x65, 0x25, 0xA1, 0x6A, 0x20, 0x15, 0x5F, 0xFF, 0x5E, 0xFF, 0x04, 0x5A, 0xFF, 0x53, 0xFF, 0x50, 0x22, 0x6C, 0x54, 0xFF, 0x14, 0x4D, 0xFF, 0x4A, 0x00, 0xD3, 0xFF, 0x16, 0x24, 0x1D, 0x6B, 0xFF, 0x6A, 0x15, 0x22, 0x66, 0x72, 0xD7, 0x85, 0x2F, 0xA8, 0xED, 0x5F, 0x95, 0xF9, 0xAA, 0x2E, 0xCE, 0xF0, 0x94, 0x3F, 0x75, 0x21, 0xBF, 0xD5, 0x84, 0x4D, 0x3D, 0xD5, 0x2F, 0xD0, 0xAF, 0xAC, 0xFD, 0x22, 0xFB, 0xE8, 0x26, 0x3B, 0xE0, 0x2F, 0xE7, 0x55, 0xF8, 0x2F, 0x06, 0xF1, 0x23, 0x03, 0xD9, 0x23, 0x01, 0xD3, 0x21, 0x7F, 0x55, 0xF0, 0x28, 0xC8, 0xE6, 0x21, 0x77, 0xD6, 0x23, 0x0F, 0xCC, 0x22, 0xD1, 0x55, 0xDD, 0x21, 0x89, 0xD5, 0x22, 0xBF, 0xC3, 0x22, 0xF6, 0xBB, 0x22, 0xB1, 0x55, 0xBF, 0x21, 0x61, 0xB5, 0x22, 0xB1, 0xA8, 0x21, 0x59, 0x9F, 0x22, 0xBB, 0x55, 0xAB, 0x21, 0x69, 0xA2, 0x21, 0x5F, 0x95, 0x2D, 0x23, 0x8C, 0x42, 0xD5, 0x5A, 0xD2, 0x21, 0x9F, 0xBF, 0x21, 0x95, 0x30, 0x1B, 0xCB, 0x27, 0x21, 0xC4, 0xAA, 0x21, 0xA7, 0xB0, 0x21, 0x9D, 0xA9, 0x21, 0x9F, 0xA6, 0x21, 0x7D, 0x9E, 0xAB, 0x21, 0x7F, 0x8F, 0x23, 0xA2, 0x87, 0x21, 0x77, 0x96, 0x26, 0xB9, 0x30, 0x0B, 0x51, 0x7F, 0x21, 0x19, 0x78, 0x21, 0x7F, 0x9E, 0xFF, 0x94, 0x20, 0x01, 0x45, 0x8A, 0x26, 0xCF, 0x82, 0xFF, 0x81, 0x20, 0x11, 0x8B, 0x20, 0x05, 0x62, 0x82, 0x20, 0x19, 0x30, 0x1B, 0x6E, 0xFF, 0x66, 0x21, 0xA5, 0x71, 0xA2, 0x21, 0x41, 0x68, 0x21, 0x3D, 0x63, 0xFF, 0x60, 0x21, 0x3B, 0x66, 0xA0, 0x21, 0x41, 0x5E, 0x2D, 0xBD, 0x57, 0xFF, 0x51, 0xFF, 0x4F, 0x2A, 0xFF, 0x48, 0x21, 0xC5, 0x70, 0x20, 0x21, 0x68, 0x80, 0x17, 0x6A, 0xAA, 0x20, 0x25, 0x63, 0x21, 0x63, 0x57, 0x20, 0x1D, 0x50, 0x20, 0x1F, 0x55, 0x20, 0xFF, 0x4E, 0x20, 0x01, 0x46, 0xFF, 0x47, 0xFF, 0x40, 0x0A, 0xFF, 0x3F, 0xFF, 0x39, 0x20, 0x07, 0x3F, 0x20, 0x09, 0x39, 0xA2, 0x20, 0x09, 0x32, 0x20, 0x01, 0x2C, 0xFF, 0x5D, 0x23, 0xF6, 0x53, 0xC0, 0x20, 0x23, 0x30, 0x03, 0x49, 0xFF, 0x44, 0xFF, 0x4B, 0xFF, 0x10, 0x45, 0xFF, 0x42, 0x21, 0x3E, 0x40, 0xFF, 0x3C, 0xFF, 0x05, 0x38, 0xFF, 0x34, 0xFF, 0x4A, 0x20, 0x39, 0x41, 0x21, 0x4E, 0x50, 0x43, 0x20, 0x05, 0x3B, 0x20, 0x11, 0x38, 0xFF, 0x35, 0xFF, 0x00, 0x31, 0xFF, 0x2E, 0xFF, 0x33, 0xFF, 0x30, 0xFF, 0x55, 0x2B, 0x23, 0x46, 0x3B, 0x20, 0x0F, 0x33, 0x20, 0x0F, 0x30, 0x24, 0xD2, 0x05, 0x2A, 0xFF, 0x26, 0xFF, 0x2D, 0x2B, 0x94, 0x27, 0x2D, 0xA5, 0x01, 0x23, 0xFF, 0x20, 0xFF, 0x1E, 0xFF, 0x1B, 0x23, 0x68, 0x50, 0x26, 0x40, 0x0B, 0x24, 0x2D, 0xB9, 0x1E, 0xFF, 0x1C, 0xFF, 0x05, 0x1D, 0xFF, 0x1A, 0xFF, 0x18, 0x21, 0xD2, 0x18, 0x24, 0xB8, 0x15, 0x13, 0xFF, 0x12, 0x33, 0x8B, 0x00, 0x20, 0x36, 0xD2, 0x6B, 0xF6, 0xB5, 0x34, 0x85, 0x00, 0x24, 0x87, 0x64, 0xB3, 0xFA, 0x2C, 0x0B, 0xEA, 0x24, 0x61, 0x55, 0xE4, 0x24, 0x57, 0xCC, 0x24, 0x59, 0xC6, 0x27, 0xFF, 0xDF, 0x24, 0x75, 0x52, 0xDA, 0x24, 0x5F, 0xC1, 0x24, 0x4D, 0xBC, 0x00, 0x22, 0xB6, 0x00, 0xC5, 0x23, 0x56, 0x43, 0x7B, 0xFE, 0xFF, 0xF2, 0x34, 0xA5, 0x00, 0x23, 0x4E, 0xAA, 0x24, 0xFD, 0xED, 0x2A, 0x35, 0xEA, 0x2C, 0x67, 0xD5, 0x24, 0xE9, 0xD2, 0xAA, 0x24, 0x91, 0xB7, 0x24, 0x8F, 0xB2, 0x29, 0x02, 0xCD, 0x24, 0xA5, 0xCA, 0xAA, 0x25, 0x7E, 0xAF, 0x24, 0x81, 0xAB, 0x25, 0x86, 0xB0, 0x23, 0x01, 0xAA, 0xAA, 0x23, 0x4B, 0x96, 0x23, 0x4D, 0x90, 0x23, 0x5B, 0xA4, 0x23, 0x09, 0x9F, 0xAA, 0x2E, 0xFF, 0x8A, 0x23, 0x35, 0x85, 0x22, 0xED, 0x7D, 0x22, 0xE9, 0x77, 0xAA, 0x22, 0xDB, 0x67, 0x22, 0xD9, 0x62, 0x22, 0xE7, 0x72, 0x23, 0x39, 0x6D, 0xAA, 0x22, 0xE3, 0x5C, 0x22, 0xE5, 0x57, 0x23, 0x6B, 0x9A, 0x23, 0x37, 0x96, 0xAA, 0x23, 0x17, 0x80, 0x23, 0x19, 0x7C, 0x23, 0x77, 0x93, 0x23, 0x29, 0x90, 0xAA, 0x25, 0x4A, 0x79, 0x23, 0x21, 0x76, 0x22, 0xFF, 0x6A, 0x23, 0x01, 0x65, 0xAA, 0x24, 0x7A, 0x53, 0x22, 0xF9, 0x50, 0x28, 0xA9, 0x62, 0x23, 0x09, 0x5F, 0xAA, 0x25, 0x6C, 0x4D, 0x23, 0x01, 0x4A, 0x21, 0x7F, 0x53, 0x25, 0x78, 0x4E, 0xA2, 0x21, 0x77, 0x42, 0x21, 0x79, 0x3D, 0xFF, 0x52, 0x21, 0x85, 0x4E, 0xAA, 0x21, 0x87, 0x40, 0x21, 0x7D, 0x3C, 0x21, 0x7F, 0x3A, 0x21, 0x69, 0x35, 0xAA, 0x21, 0x6F, 0x2D, 0x25, 0xA4, 0x28, 0x2E, 0xFD, 0x30, 0x21, 0x65, 0x2C, 0xAA, 0x41, 0x53, 0x1E, 0x21, 0x61, 0x1B, 0x21, 0x9F, 0x41, 0x21, 0xDD, 0x3D, 0xAA, 0x21, 0xAB, 0x31, 0x21, 0x99, 0x2D, 0x21, 0xA7, 0x3B, 0x21, 0xAF, 0x38, 0xAA, 0x21, 0x9F, 0x2B, 0x21, 0xA1, 0x29, 0x24, 0xE8, 0x23, 0x21, 0x95, 0x20, 0xAA, 0x21, 0x77, 0x18, 0x21, 0x79, 0x15, 0x21, 0x87, 0x1E, 0x2F, 0x43, 0x1C, 0xAA, 0x21, 0x83, 0x13, 0x23, 0x5E, 0x12, 0x2F, 0x4F, 0x1D, 0x40, 0x1B, 0x19, 0x8A, 0x23, 0x6C, 0x14, 0xFF, 0x11, 0x26, 0x72, 0x14, 0x23, 0x76, 0x11, 0xA8, 0x20, 0x09, 0x0E, 0x20, 0x01, 0x0B, 0x21, 0xA3, 0x10, 0xFF, 0x0F, 0x20, 0xFF, 0x0D, 0x40, 0x03, 0x0B, 0xFF, 0x0A, 0xFF, 0x0C, 0xAA, 0x20, 0x03, 0x09, 0x25, 0x24, 0x08, 0x25, 0x28, 0x06, 0x25, 0x32, 0x13, 0xAA, 0x20, 0x1D, 0x10, 0x20, 0x1F, 0x0C, 0x20, 0x15, 0x0A, 0x25, 0x3C, 0x0F, 0xAB, 0x20, 0x33, 0x0D, 0x20, 0x27, 0x08, 0x20, 0x1D, 0x07, 0x25, 0x52, 0x50, 0x25, 0x56, 0x04, 0x20, 0x01, 0x03, 0x25, 0x76, 0x02, 0x80, 0x07, 0x50, 0x01, 0x01, 0xAC, 0x00, 0xB9, 0x7F, 0x20, 0x2C, 0x1D, 0x03, 0x04, 0xE9, 0x7F, 0x10, 0x04, 0x80, 0x59, 0x30, 0xC2, 0x30, 0xFE, 0xE2, 0x2C, 0x3A, 0x3A, 0x46, 0x20, 0xF8, 0xE9, 0xFF, 0x0C, 0x00, 0x95, 0x00, 0xDC, 0x00, 0x3E, 0x2E, 0x03, 0x1F, 0xA9, 0x80, 0xF2, 0x18, 0x00, 0x10, 0xF9, 0x38, 0xEF, 0x4F, 0x02, 0x50, 0x90, 0xFF, 0x1F, 0xFF, 0xC0, 0xD0, 0x00, 0xDE, 0x98, 0xBF, 0x1B, 0xCB, 0xFF, 0x2F, 0x23, 0xF2, 0x7F, 0xE2, 0x4B, 0xFF, 0x01, 0xCF, 0x27, 0x10, 0x5B, 0x20, 0x2B, 0x10, 0x00, 0x11, 0x49, 0x71, 0x11, 0xFD, 0x60, 0x07, 0xF9, 0x7E, 0x70, 0x17, 0x0B, 0x10, 0x1F, 0x3A, 0x6E, 0x0C, 0xBA, 0x5C, 0x40, 0x41, 0xCD, 0x00, 0x30, 0xE3, 0xFF, 0x20, 0xF9, 0xB7, 0xFF, 0xFF, 0x00, 0xAF, 0xCF, 0x03, 0xD1, 0xF8, 0xFF, 0x7F, 0xFE, 0x00, 0xFF, 0x0C, 0x05, 0x06, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x90, 0x80, 0xED, 0xFF, 0xEE, 0xFF, 0x79, 0x0A, 0x00, 0x77, 0x00, 0xEE, 0x20, 0x07, 0x77, 0x20, 0x07, 0x00, 0x01, 0xAA, 0x00, 0x07, 0xFF, 0xFF, 0x3F, 0xCF, 0x2B, 0x90, 0x06, 0xA5, 0x00, 0x00, 0xF9, 0xF8, 0x70, 0x17, 0x80, 0x1F, 0x4A, 0x00, 0x00, 0xA0, 0x6F, 0x6F, 0xF0, 0x30, 0x00, 0x9B, 0x07, 0x00, 0x00, 0xEF, 0x23, 0x00, 0x80, 0x37, 0x80, 0x3F, 0xEA, 0x05, 0x8B, 0x00, 0x30, 0x1F, 0x80, 0xE8, 0xAB, 0x59, 0xF7, 0x59, 0x00, 0x60, 0x3F, 0x3B, 0xFC, 0xE0, 0x6B, 0xF2, 0x00, 0xE0, 0x5F, 0x00, 0x90, 0x7F, 0xA2, 0x00, 0x6A, 0xF4, 0xF3, 0x2A, 0x9F, 0x8F, 0x90, 0xBF, 0xDE, 0x20, 0xDF, 0x97, 0xDC, 0x48, 0x01, 0x00, 0x20, 0x10, 0x7B, 0xFF, 0x02, 0xAF, 0xFC, 0x30, 0x20, 0xFF, 0xFA, 0x39, 0xE3, 0x4E, 0xFF, 0x00, 0x04, 0x00, 0x00, 0x65, 0x50, 0x01, 0xA9, 0x88, 0x05, 0x04, 0xFF, 0x02, 0xF6, 0x1E, 0x8F, 0xB0, 0x50, 0xEF, 0x00, 0x4A, 0x9F, 0x01, 0x4B, 0x05, 0x08, 0x3C, 0x8F, 0x70, 0x90, 0x21, 0xCF, 0x70, 0xA1, 0xFA, 0x41, 0x45, 0x0C, 0xFF, 0xEF, 0x02, 0x00, 0x20, 0xC5, 0x2A, 0xD9, 0x80, 0x80, 0x80, 0x30, 0x03, 0xFF, 0xFE, 0x05, 0x0B, 0xF8, 0xE1, 0x6F, 0x81, 0x2B, 0x97, 0x80, 0x90, 0x00, 0x05, 0x60, 0x00, 0x2F, 0x66, 0x00, 0xB6, 0xFF, 0xFF, 0x25, 0x06, 0x06, 0x1F, 0xF8, 0x08, 0xF8, 0x9F, 0xF8, 0xF7, 0x2F, 0x73, 0x06, 0x07, 0xBB, 0x90, 0x21, 0x06, 0xD0, 0x40, 0x3B, 0xBB, 0xB8, 0x00, 0x6F, 0x6F, 0x00, 0x70, 0xF0, 0x6F, 0x6F, 0xE0, 0xE0, 0x68, 0xDF, 0x02, 0x50, 0xA0, 0xDF, 0xDF, 0x90, 0x90, 0x20, 0x0B, 0xF0, 0x08, 0x4B, 0x00, 0xB0, 0x00, 0x20, 0x0B, 0xA0, 0x9B, 0x00, 0x00, 0x70, 0x00, 0x89, 0xFF, 0xB6, 0x8D, 0xFF, 0xFF, 0x00, 0x04, 0x03, 0xAD, 0xFD, 0x23, 0x2F, 0xF3, 0xF3, 0x24, 0x9F, 0xAF, 0x20, 0x0B, 0x04, 0xBB, 0x2D, 0xB5, 0xF3, 0xF3, 0x00, 0xAF, 0xBF, 0xB2, 0x00, 0x8B, 0x00, 0xE8, 0xB0, 0x00, 0xFF, 0xEF, 0xC0, 0xC0, 0xFF, 0xFF, 0x49, 0x10, 0x0C, 0x81, 0xFD, 0x90, 0xC1, 0x2B, 0x9B, 0x20, 0x0B, 0x90, 0x00, 0x00, 0xBB, 0x00, 0xA0, 0x21, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xB3, 0x00, 0xCC, 0x07, 0x7C, 0xFA, 0x68, 0xAC, 0x00, 0xFB, 0x89, 0x00, 0x0A, 0x95, 0xFA, 0x5F, 0x48, 0x00, 0xF8, 0xF9, 0x03, 0x06, 0x72, 0xFA, 0xBD, 0x21, 0x00, 0x9D, 0x01, 0x17, 0x0D, 0xF9, 0xF9, 0x01, 0x00, 0x00, 0xB7, 0x00, 0x58, 0xDF, 0xDB, 0xD8, 0x4F, 0x3F, 0x00, 0x30, 0x20, 0x3A, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x01, 0x38, 0x6A, 0x4F, 0x4F, 0x20, 0x30, 0x3B, 0x2E, 0x19, 0x04, 0xFF, 0xFF, 0x4A, 0x0B, 0xBB, 0x2E, 0x18, 0x70, 0xFA, 0x00, 0xCC, 0x5E, 0xFF, 0xFF, 0x09, 0x08, 0xFA, 0xFA, 0x00, 0x8F, 0x8F, 0xF3, 0xF3, 0x8F, 0x7F, 0xFF, 0xFC, 0x00, 0x08, 0x3D, 0x91, 0x00, 0xDD, 0x00, 0xF3, 0xF9, 0x00, 0x8F, 0x9F, 0xBA, 0x00, 0x6B, 0x00, 0x00, 0xB0, 0x00, 0xC7, 0xAF, 0xF4, 0xF7, 0x6F, 0x7F, 0xDC, 0x70, 0x00, 0x19, 0xDF, 0x30, 0x30, 0xFF, 0xFF, 0xF5, 0xC0, 0x00, 0x6F, 0x9F, 0x10, 0x00, 0xD8, 0x00, 0x30, 0x60, 0x01, 0xFF, 0xEF, 0xDB, 0x12, 0x2A, 0x00, 0x31, 0x2E, 0x70, 0x20, 0x09, 0x0C, 0x34, 0xF2, 0xFF, 0xFE, 0x00, 0x10, 0xFD, 0x22, 0xFF, 0x09, 0x5B, 0xEB, 0x40, 0x40, 0xB0, 0x20, 0x2B, 0xFF, 0x0D, 0x9F, 0x1E, 0x08, 0x09, 0x20, 0x1F, 0xAE, 0x7F, 0x05, 0x09, 0xE4, 0x31, 0x08, 0x40, 0x00, 0xFF, 0xE4, 0x3F, 0x49, 0x9F, 0xFF, 0x02, 0x07, 0xBF, 0xFA, 0x30, 0xFF, 0xC8, 0x00, 0x0F, 0x49, 0x23, 0xFC, 0x24, 0x02, 0x7F, 0xEE, 0x24, 0x02, 0x40, 0x07, 0x00, 0x05, 0xFA, 0x60, 0x17, 0x70, 0x1F, 0x00, 0x05, 0xFA, 0x09, 0x90, 0x1F, 0x60, 0x87, 0xD0, 0xBF, 0x55, 0xFA, 0x20, 0xFB, 0xF9, 0xFF, 0xFF, 0x02, 0x8C, 0xAF, 0x03, 0xFF, 0x5E, 0x04, 0x10, 0x16, 0x4D, 0xE6, 0x43, 0x02, 0x4C, 0x49, 0x4D, 0xFF, 0xFE, 0x14, 0x2F, 0xFF, 0x02, 0x30, 0x02, 0x28, 0x26, 0xF7, 0x38, 0x90, 0x69, 0x6D, 0x61, 0x67, 0xA8, 0x37, 0x02, 0x80, 0x27, 0xBE, 0x0D, 0x67, 0x0F, 0x2B, 0xEA, 0x91, 0x00, 0xE1, 0x95, 0x34, 0xA7, 0x5B, 0x58, 0x01, 0xAD, 0x00, 0x9B, 0xEF, 0x2F, 0x93, 0x39, 0x5F, 0x2E, 0x47, 0x00, 0x1A, 0x26, 0x38, 0x61, 0xA5, 0x72, 0xFA, 0x4F, 0x00, 0xFE, 0x8B, 0x89, 0x49, 0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char Nintendo_LicensedBy_LZ[0x2000] =
+{
+ 0x11, 0x48, 0x65, 0x00, 0x00, 0x64, 0x61, 0x72, 0x63, 0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x28, 0x65, 0x00, 0x00, 0x83, 0x30, 0x09, 0x32, 0x04, 0x00, 0x00, 0x60, 0x20, 0x03, 0x30, 0x13, 0xAB, 0x30, 0x18, 0x15, 0x20, 0x1D, 0x02, 0xA0, 0x0B, 0x06, 0x20, 0x2B, 0x30, 0x18, 0x5A, 0x09, 0x20, 0x35, 0x10, 0x20, 0x39, 0x30, 0x2B, 0xF8, 0x20, 0x41, 0x54, 0x85, 0x30, 0x0B, 0x05, 0x00, 0x00, 0xEC, 0x20, 0x4D, 0x98, 0x30, 0x17, 0xD0, 0x20, 0x28, 0x30, 0x17, 0xDC, 0x30, 0x23, 0x07, 0x00, 0x00, 0xCC, 0x09, 0x0C, 0x00, 0x00, 0x20, 0x20, 0x51, 0x40, 0x14, 0x20, 0x2B, 0xA0, 0x20, 0x0B, 0x64, 0x20, 0x5D, 0xA0, 0x20, 0x00, 0x00, 0x4C, 0x99, 0x20, 0x5C, 0xA8, 0x01, 0x50, 0x53, 0x20, 0x22, 0x00, 0xB2, 0x30, 0x75, 0x0A, 0x23, 0x00, 0x00, 0xB4, 0x20, 0x74, 0xE2, 0x20, 0x81, 0xC0, 0x09, 0x25, 0x00, 0x00, 0x3C, 0x20, 0x68, 0x12, 0x02, 0x50, 0x77, 0xA0, 0x30, 0x8F, 0x1C, 0x20, 0x90, 0x00, 0x36, 0x00, 0x00, 0x28, 0xA6, 0x20, 0xAB, 0x3E, 0x20, 0x9C, 0x80, 0x3A, 0x20, 0x0B, 0x20, 0xAD, 0x60, 0xAA, 0x30, 0x17, 0x3C, 0x50, 0x17, 0x82, 0x30, 0x17, 0x40, 0x20, 0x23, 0x08, 0x16, 0x00, 0x00, 0xA4, 0x30, 0x2F, 0x49, 0x20, 0x67, 0x20, 0xE9, 0xC4, 0xAB, 0x30, 0x3B, 0x4A, 0x50, 0x17, 0xDC, 0x30, 0x3B, 0x52, 0x20, 0x47, 0x20, 0xE0, 0x59, 0xF4, 0x30, 0x53, 0x55, 0x20, 0x53, 0x30, 0xD4, 0x00, 0x2E, 0x21, 0x13, 0x01, 0x61, 0x00, 0x6E, 0x00, 0x69, 0x00, 0x6D, 0x21, 0x1D, 0x41, 0x4E, 0x20, 0x07, 0x6E, 0x00, 0x74, 0x00, 0x65, 0x20, 0x11, 0x05, 0x64, 0x00, 0x6F, 0x00, 0x4C, 0x20, 0x03, 0x67, 0x20, 0x07, 0x14, 0x5F, 0x00, 0x44, 0x20, 0x03, 0x30, 0x20, 0x01, 0x5F, 0x00, 0x10, 0x53, 0x00, 0x63, 0x40, 0x1F, 0x65, 0x00, 0x4F, 0x00, 0x55, 0x75, 0x20, 0x2B, 0x41, 0x20, 0x43, 0x62, 0x20, 0x13, 0x6C, 0x40, 0x47, 0xAB, 0x02, 0x50, 0x43, 0x42, 0x03, 0x20, 0x43, 0x43, 0x01, 0x80, 0x87, 0x55, 0x03, 0x20, 0xCB, 0x00, 0x90, 0x43, 0xEB, 0x01, 0x90, 0xCB, 0x00, 0x90, 0x87, 0xF0, 0xCB, 0x62, 0x21, 0x5D, 0x79, 0x21, 0x97, 0x01, 0x31, 0xA1, 0xF5, 0x71, 0x8D, 0x00, 0xF0, 0x2F, 0x71, 0x05, 0xD0, 0x2F, 0x74, 0x42, 0x09, 0x67, 0x23, 0x29, 0x5E, 0x33, 0x22, 0x01, 0x73, 0xA2, 0x01, 0xB0, 0x5B, 0x52, 0x2D, 0x00, 0x10, 0x21, 0x31, 0xAA, 0x01, 0x00, 0x21, 0x32, 0x01, 0x00, 0x43, 0x33, 0xE0, 0x65, 0x4C, 0x23, 0x71, 0x4D, 0x8F, 0x22, 0xA3, 0x73, 0x00, 0x6B, 0x00, 0x40, 0x85, 0x30, 0x1F, 0x00, 0xB0, 0x17, 0xF0, 0x93, 0xAA, 0xF2, 0xE3, 0x5F, 0x22, 0xE5, 0x69, 0x62, 0xD3, 0x73, 0x22, 0xF9, 0x64, 0xA8, 0x22, 0x8D, 0x79, 0x22, 0xF1, 0x31, 0x20, 0xAB, 0x38, 0x00, 0x78, 0xB0, 0x23, 0x7E, 0x34, 0xE0, 0xF7, 0x00, 0x10, 0x02, 0x43, 0x4C, 0x41, 0x4E, 0x23, 0xFF, 0xFE, 0x23, 0xF0, 0x00, 0x02, 0x02, 0x34, 0x23, 0x33, 0xB6, 0x0E, 0x70, 0x61, 0x74, 0x31, 0x23, 0xA2, 0x44, 0x5E, 0x34, 0x79, 0x28, 0x88, 0x33, 0x93, 0xFF, 0xFF, 0xFF, 0x34, 0x6C, 0x53, 0x63, 0x65, 0x02, 0x6E, 0x65, 0x4F, 0x75, 0x74, 0x41, 0x24, 0x91, 0x47, 0x04, 0x5F, 0x41, 0x5F, 0x30, 0x30, 0xD0, 0x56, 0x70, 0x61, 0x33, 0x69, 0x31, 0x33, 0xC3, 0x50, 0x3F, 0x02, 0x00, 0x30, 0x59, 0x34, 0xBD, 0x40, 0x68, 0x24, 0xC1, 0x50, 0x5F, 0x4E, 0x69, 0x6E, 0x4C, 0x1C, 0x6F, 0x67, 0x6F, 0xA0, 0x35, 0x34, 0xC0, 0x34, 0xDD, 0x43, 0x4C, 0x23, 0x56, 0x43, 0x74, 0x5F, 0x00, 0x10, 0x02, 0x40, 0x87, 0x40, 0x0B, 0xC8, 0xD0, 0x5D, 0x20, 0x76, 0x7F, 0x43, 0x35, 0x0C, 0x4E, 0x5F, 0x52, 0x1C, 0x6F, 0x6F, 0x74, 0xD0, 0x7E, 0x00, 0x70, 0x4B, 0x80, 0x57, 0x00, 0x20, 0xFE, 0x20, 0x3B, 0x50, 0x3F, 0x00, 0x30, 0xFF, 0x35, 0x17, 0xB0, 0xFF, 0x24, 0xF2, 0x80, 0xFF, 0x00, 0x35, 0x00, 0x1E, 0x45, 0x6C, 0x70, 0xFF, 0x42, 0x40, 0xFF, 0x42, 0x00, 0x40, 0xFF, 0x6C, 0x9C, 0x80, 0x2D, 0x90, 0xFF, 0x5C, 0x01, 0xE0, 0xFF, 0x90, 0xB3, 0x34, 0xC2, 0xBE, 0x02, 0xD0, 0xF3, 0xC8, 0x20, 0xAA, 0xD0, 0xF3, 0x01, 0x71, 0xFF, 0x31, 0x39, 0x71, 0xFF, 0x65, 0xE2, 0x23, 0x51, 0xB1, 0xFF, 0x31, 0x84, 0x47, 0x5F, 0x43, 0x00, 0x81, 0xFF, 0x0F, 0xCC, 0xE1, 0xFF, 0x02, 0x90, 0xFF, 0x12, 0xC3, 0x02, 0x31, 0xF3, 0x92, 0x3F, 0x80, 0xBF, 0xBD, 0x91, 0xF3, 0x60, 0x32, 0xB6, 0x00, 0x82, 0xFF, 0x36, 0xFF, 0x03, 0x32, 0xFF, 0x7C, 0x27, 0x47, 0xAA, 0x53, 0x3F, 0x0D, 0x42, 0xFF, 0x48, 0x27, 0xBD, 0xB0, 0x27, 0xC1, 0xA4, 0xB0, 0x27, 0xAD, 0x24, 0x27, 0xA8, 0x36, 0xEB, 0x30, 0x03, 0x00, 0x00, 0x56, 0xBC, 0x20, 0x03, 0x24, 0x27, 0xCB, 0x88, 0x37, 0x93, 0x27, 0xB4, 0xB0, 0x81, 0x27, 0x07, 0x74, 0x0A, 0x00, 0x00, 0x78, 0x0B, 0x32, 0xDF, 0x7C, 0x57, 0x00, 0x03, 0x5B, 0x37, 0x52, 0x27, 0x8E, 0x26, 0xD1, 0x33, 0xB7, 0x50, 0x41, 0xB8, 0x83, 0x2F, 0x02, 0xF2, 0xE3, 0x73, 0xDB, 0x01, 0x13, 0x07, 0x50, 0x5F, 0x33, 0xBB, 0x00, 0x80, 0x67, 0xB8, 0x60, 0x67, 0x20, 0xAA, 0x43, 0xC7, 0x38, 0x63, 0xC7, 0x30, 0x6F, 0xA9, 0x93, 0x9F, 0xA0, 0x24, 0x0A, 0xA0, 0x27, 0xC5, 0x80, 0xBE, 0x24, 0x39, 0x91, 0x23, 0x16, 0xA0, 0xC0, 0x48, 0x99, 0x06, 0x02, 0x00, 0x30, 0x37, 0x80, 0x70, 0x23, 0x33, 0x33, 0xB3, 0x3F, 0xFC, 0x2D, 0xEC, 0x46, 0xBC, 0x70, 0x0B, 0x0A, 0xD7, 0x23, 0x20, 0x0B, 0x30, 0x2F, 0x80, 0x5E, 0x3F, 0x48, 0xC9, 0x07, 0x01, 0xD0, 0x2F, 0xF4, 0x2F, 0xB0, 0x6B, 0x39, 0x2C, 0x40, 0x37, 0x9D, 0x1C, 0x30, 0x97, 0x61, 0xEF, 0xCC, 0x28, 0x65, 0x30, 0x9B, 0x70, 0xF3, 0xEE, 0x24, 0x87, 0xE4, 0xB9, 0x71, 0x5B, 0x50, 0xF1, 0x5B, 0x29, 0x59, 0xD4, 0x8B, 0x80, 0x0B, 0x41, 0xCD, 0xCC, 0xCC, 0x20, 0xEB, 0x20, 0x34, 0x02, 0x00, 0x41, 0x67, 0xF3, 0x00, 0x14, 0xBB, 0x30, 0x7F, 0x30, 0x2F, 0x71, 0x73, 0x44, 0x73, 0xF5, 0x38, 0x01, 0xA0, 0x7F, 0x51, 0xC1, 0x20, 0x7F, 0x3E, 0x02, 0xD0, 0x7F, 0x52, 0x65, 0x64, 0x01, 0x70, 0xFF, 0xC2, 0xC1, 0xEB, 0x45, 0x43, 0xC2, 0xB7, 0x6D, 0xDB, 0x20, 0x7F, 0x8C, 0x9A, 0x25, 0x02, 0x20, 0xC1, 0x00, 0xD1, 0x8B, 0xB6, 0x72, 0x5C, 0xA4, 0x87, 0xB4, 0x85, 0x41, 0x3B, 0x92, 0x24, 0xE9, 0xC0, 0x60, 0x8B, 0x31, 0x00, 0x32, 0xE7, 0xEB, 0x35, 0x33, 0xF2, 0xE7, 0x92, 0x53, 0xF0, 0x26, 0x82, 0x20, 0x25, 0x1B, 0x90, 0x0B, 0xFD, 0x50, 0x97, 0x34, 0xEF, 0x00, 0x50, 0x97, 0x96, 0x53, 0x30, 0x3B, 0x77, 0x0E, 0xAA, 0xF1, 0x17, 0x7F, 0x32, 0x02, 0x13, 0x73, 0x32, 0xF7, 0x50, 0x8B, 0x00, 0x96, 0x7B, 0x33, 0x1B, 0x57, 0x82, 0x00, 0x31, 0x7F, 0xCD, 0x3B, 0xB0, 0x57, 0x07, 0x54, 0x53, 0x2B, 0x0E, 0x47, 0x73, 0x4C, 0x37, 0x8B, 0xBB, 0x2B, 0xF9, 0x94, 0x63, 0x8B, 0x3B, 0xA7, 0x3B, 0xF1, 0x24, 0x4B, 0xF5, 0x00, 0x01, 0x97, 0x0F, 0xC0, 0x39, 0x8E, 0xE3, 0x2B, 0x59, 0x51, 0x5B, 0x5C, 0x1D, 0x01, 0x20, 0x23, 0x40, 0x03, 0xF7, 0x6B, 0x40, 0x41, 0x9E, 0x15, 0x8D, 0xBD, 0x8D, 0x31, 0xA3, 0x9A, 0x99, 0xB9, 0x2B, 0x9D, 0x2C, 0x7A, 0x04, 0x01, 0x10, 0x23, 0x55, 0x01, 0x01, 0x20, 0x8F, 0x01, 0x01, 0x20, 0x8F, 0x01, 0x00, 0x10, 0x8F, 0xC1, 0x20, 0x8F, 0x6C, 0x3D, 0x60, 0x8F, 0x44, 0x5B, 0x01, 0x00, 0x10, 0x8F, 0x00, 0x00, 0x23, 0x50, 0x5F, 0x10, 0x42, 0x6C, 0x6B, 0x03, 0xE1, 0x63, 0x9A, 0x99, 0x19, 0xC0, 0x1F, 0x0E, 0x74, 0xDA, 0x00, 0xC1, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0xF5, 0x00, 0x40, 0x23, 0x03, 0x81, 0x63, 0x00, 0x13, 0xBB, 0x00, 0x32, 0xC7, 0x58, 0x2E, 0xBD, 0x88, 0x66, 0x4F, 0x55, 0xE8, 0x2E, 0xC9, 0x18, 0x2E, 0xB5, 0x48, 0x2E, 0xB9, 0x78, 0x62, 0xC7, 0xF7, 0xE3, 0xD3, 0x56, 0x3F, 0x60, 0x0B, 0x52, 0xD3, 0xF0, 0xC2, 0xD3, 0x01, 0xC0, 0x2F, 0x22, 0xDF, 0xBB, 0xD4, 0x33, 0x40, 0x68, 0x03, 0x50, 0x0B, 0x52, 0xEB, 0xF0, 0xC2, 0xEB, 0x01, 0xB0, 0x2F, 0xFF, 0x32, 0xF7, 0x01, 0xB0, 0xBF, 0x33, 0x03, 0x01, 0xC0, 0x2F, 0x00, 0x10, 0xBF, 0x45, 0x73, 0x70, 0x0B, 0x53, 0x1B, 0xFF, 0x40, 0xBF, 0x83, 0x1B, 0x01, 0xB0, 0x2F, 0x63, 0x27, 0x03, 0xC1, 0xC3, 0x33, 0x27, 0x75, 0x97, 0x93, 0x33, 0xFF, 0x00, 0x91, 0xC3, 0x01, 0x00, 0x2F, 0x05, 0xE1, 0xC3, 0x00, 0xF0, 0xBF, 0xF1, 0xC3, 0x01, 0x00, 0x2F, 0x05, 0x01, 0xC3, 0x00, 0x16, 0xB7, 0xFA, 0x00, 0x36, 0x4F, 0x35, 0xCC, 0x33, 0x8B, 0x36, 0x53, 0x33, 0x8F, 0xA0, 0x69, 0xE3, 0xD0, 0xFF, 0x6D, 0xAB, 0xE6, 0xCF, 0x59, 0xC7, 0x26, 0x43, 0x00, 0x40, 0x17, 0x26, 0x37, 0xD6, 0xFF, 0x63, 0x57, 0xFF, 0x26, 0x2B, 0x00, 0x30, 0x17, 0x36, 0x1F, 0x00, 0x30, 0x5F, 0x36, 0x13, 0x00, 0x40, 0x17, 0x00, 0x10, 0x5F, 0x48, 0x6B, 0xFF, 0x35, 0xFB, 0x00, 0x30, 0x17, 0x65, 0xEF, 0x03, 0xC1, 0x03, 0x82, 0xC7, 0xE1, 0x03, 0x82, 0xDF, 0x02, 0xE1, 0x03, 0xFB, 0x73, 0x27, 0xF1, 0x03, 0x80, 0x17, 0x01, 0xE1, 0x03, 0x00, 0xFF, 0xDF, 0x54, 0xEC, 0xDF, 0x02, 0x7E, 0xDF, 0x75, 0x04, 0x2F, 0xA4, 0x5F, 0x0D, 0xDC, 0xDF, 0x50, 0x2F, 0xCC, 0xB8, 0x2F, 0xD0, 0x55, 0x20, 0x2F, 0xBC, 0xA0, 0x2F, 0xC0, 0x2C, 0x2C, 0xE3, 0xAC, 0x2C, 0xE7, 0x52, 0x10, 0x2C, 0xDF, 0x74, 0x2C, 0xDF, 0xD8, 0x07, 0x2D, 0x17, 0x09, 0xFE, 0x2C, 0x31, 0x2C, 0xE3, 0x02, 0x9C, 0xDF, 0x3E, 0xCF, 0x00, 0xFC, 0xDF, 0x9E, 0xF3, 0x00, 0xBC, 0xDF, 0x7C, 0xBF, 0xEC, 0xDF, 0x2C, 0x6D, 0x5B, 0xDD, 0x4F, 0x4C, 0xE3, 0x8C, 0xD3, 0xD0, 0x17, 0x9C, 0xBB, 0xFD, 0x00, 0x30, 0x17, 0x00, 0x9F, 0xD3, 0x3F, 0xFD, 0x01, 0x1C, 0x8B, 0x00, 0x0D, 0xE7, 0xC3, 0xA3, 0xA0, 0x81, 0xF3, 0xFB, 0x00, 0x9F, 0xFB, 0x30, 0x23, 0x01, 0x1C, 0x73, 0x03, 0xD0, 0x67, 0x02, 0x7C, 0x5B, 0x70, 0x2B, 0xCB, 0x7C, 0x5B, 0x7F, 0x20, 0x3B, 0xDB, 0x00, 0xEB, 0xC3, 0x3E, 0x67, 0x7F, 0xD7, 0x5B, 0xCF, 0x00, 0xFC, 0x4F, 0x00, 0xDC, 0xDB, 0x7D, 0xF0, 0x2C, 0xCB, 0x80, 0x7F, 0x01, 0x2C, 0xDB, 0x30, 0x2F, 0x7F, 0xFB, 0xC8, 0x2F, 0x03, 0xFF, 0x7C, 0xDB, 0x5B, 0xE7, 0xAC, 0xDB, 0x00, 0x4C, 0x4F, 0x03, 0x3D, 0x67, 0x00, 0x1E, 0x67, 0xDD, 0x67, 0x04, 0x1C, 0x67, 0xFF, 0x41, 0xA3, 0x79, 0x93, 0x9D, 0x43, 0xCC, 0x67, 0x00, 0x60, 0x23, 0xCC, 0x67, 0x31, 0xEB, 0x89, 0x7B, 0xFF, 0x28, 0x2F, 0x00, 0x3C, 0x67, 0x00, 0x50, 0x23, 0xDC, 0x67, 0x00, 0x50, 0x8F, 0xDC, 0x67, 0x00, 0x60, 0x23, 0x00, 0x10, 0x8F, 0xF9, 0x79, 0x4B, 0x30, 0x8F, 0x00, 0x2C, 0x67, 0x00, 0x50, 0x23, 0x04, 0x1C, 0x67, 0x70, 0xC2, 0xA9, 0x33, 0xFF, 0x00, 0x81, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0x03, 0x81, 0x63, 0x01, 0x5C, 0x67, 0xFF, 0x01, 0x9F, 0x2F, 0x43, 0xEB, 0x6F, 0x2F, 0x9F, 0x97, 0xDF, 0x2F, 0x00, 0x60, 0x23, 0xCF, 0x2F, 0x34, 0x33, 0xFF, 0x7F, 0x2F, 0x38, 0x2F, 0x00, 0x3F, 0x2F, 0x00, 0x50, 0x23, 0xDF, 0x2F, 0x00, 0x50, 0x8F, 0xDF, 0x2F, 0x00, 0x60, 0x23, 0xFF, 0x00, 0x10, 0x8F, 0x6F, 0x2F, 0x40, 0x8F, 0x00, 0x2F, 0x2F, 0x00, 0x50, 0x23, 0x01, 0x7C, 0x07, 0x01, 0xB1, 0x63, 0x9F, 0x2F, 0xFF, 0x00, 0x91, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0x03, 0x81, 0x63, 0x01, 0x5B, 0xA7, 0xFF, 0x01, 0x95, 0x8F, 0x46, 0x27, 0x6F, 0x23, 0x9F, 0xDF, 0xD5, 0x8F, 0x00, 0x60, 0x23, 0xC5, 0x8F, 0x4F, 0xDF, 0xFF, 0x6F, 0x0B, 0x4F, 0xDF, 0x00, 0x25, 0x8F, 0x00, 0x50, 0x23, 0xD5, 0x8F, 0x00, 0x50, 0x8F, 0xD5, 0x8F, 0x00, 0x60, 0x23, 0xFF, 0x00, 0x10, 0x8F, 0x6E, 0xDB, 0x40, 0x8F, 0x00, 0x25, 0x8F, 0x00, 0x50, 0x23, 0x01, 0x7C, 0x07, 0x01, 0xB1, 0x63, 0x9E, 0xC3, 0xFF, 0x00, 0x91, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0x03, 0x61, 0x63, 0x00, 0x7C, 0x5F, 0x78, 0x4C, 0x2C, 0x5C, 0xBC, 0x5F, 0x3E, 0x51, 0x7C, 0x5F, 0x65, 0x00, 0x73, 0xC5, 0xCC, 0x5F, 0x3B, 0x9C, 0x47, 0x5F, 0x43, 0x00, 0x4C, 0x5F, 0xFC, 0x2E, 0xBB, 0x7A, 0x0F, 0x5B, 0x58, 0x4C, 0x5F, 0x3C, 0x82, 0x3B, 0xAB, 0xBC, 0x2F, 0xFF, 0xFC, 0xAB, 0x2F, 0xF8, 0x3C, 0x2E, 0xDB, 0x7C, 0x2E, 0xDF, 0xBC, 0x2E, 0xE3, 0x00, 0x3C, 0x47, 0xE5, 0x3E, 0xC7, 0x5E, 0xFB, 0x00, 0x7A, 0x3B, 0x80, 0xBF, 0x9A, 0x3B, 0x60, 0x88, 0xC7, 0xEE, 0x00, 0x3C, 0x2B, 0x00, 0x70, 0x4B, 0x9F, 0x2B, 0xCA, 0x2A, 0xB7, 0x00, 0x9B, 0xCB, 0x01, 0x10, 0x3F, 0xF2, 0xFB, 0xA0, 0x3F, 0x00, 0x1B, 0xA3, 0x01, 0xD0, 0x3F, 0x00, 0x29, 0xEF, 0x01, 0x00, 0xBF, 0x8E, 0x2B, 0x77, 0x70, 0xFF, 0xDD, 0x00, 0x27, 0x67, 0x01, 0x00, 0xFF, 0x24, 0xF0, 0x3F, 0xDF, 0x83, 0x01, 0x01, 0x3F, 0x30, 0x00, 0x8E, 0xBB, 0x95, 0x5E, 0xBF, 0x59, 0x54, 0x7E, 0xBF, 0xB4, 0x2E, 0xBC, 0x10, 0x2F, 0xFB, 0x0C, 0x6C, 0x79, 0x74, 0x31, 0x3E, 0xD1, 0x4A, 0x9E, 0x00, 0xA0, 0x80, 0x2D, 0xE7, 0x70, 0x43, 0x74, 0x78, 0x6C, 0x31, 0x34, 0xB0, 0x61, 0xFB, 0x04, 0x2F, 0xFF, 0x2D, 0x55, 0x74, 0x65, 0x6E, 0x64, 0x08, 0x6F, 0x5F, 0x4C, 0x69, 0x2E, 0xD1, 0x73, 0x65, 0x64, 0x00, 0x42, 0x79, 0x5F, 0x31, 0x32, 0x38, 0x78, 0x36, 0x01, 0x34, 0x2E, 0x62, 0x63, 0x6C, 0x69, 0x6D, 0x3F, 0xEE, 0x5C, 0x6D, 0x2F, 0x07, 0x60, 0x62, 0x2F, 0x30, 0x57, 0x4D, 0x8B, 0x4C, 0x6F, 0x23, 0x67, 0x6F, 0xAE, 0xF5, 0xFF, 0xFF, 0xFF, 0x30, 0x03, 0x00, 0x40, 0x02, 0x7C, 0x15, 0x5F, 0xEC, 0x30, 0x6E, 0xAF, 0x7E, 0x3E, 0x13, 0x5E, 0x17, 0x70, 0x61, 0x20, 0x6E, 0x31, 0x3B, 0x5B, 0x01, 0x04, 0xFF, 0x00, 0x52, 0x01, 0x6F, 0x6F, 0x74, 0x50, 0x61, 0x6E, 0x65, 0x00, 0xB0, 0xEB, 0xC3, 0x00, 0x50, 0x47, 0x50, 0xDF, 0x70, 0x61, 0x73, 0x31, 0x3B, 0xAF, 0x70, 0x53, 0x4F, 0x03, 0x20, 0x53, 0x4E, 0x5F, 0x30, 0x55, 0x00, 0x0F, 0xA2, 0x01, 0x20, 0x53, 0x4C, 0xDF, 0x42, 0x42, 0x80, 0x53, 0x69, 0x63, 0x31, 0x80, 0x3C, 0x1B, 0x07, 0x7E, 0xFF, 0x00, 0x41, 0x03, 0x7E, 0xEC, 0x2D, 0x67, 0x82, 0x2B, 0x00, 0x20, 0xEF, 0x2F, 0x6F, 0x80, 0x78, 0x42, 0xF1, 0x2B, 0x71, 0xA5, 0xCF, 0x2F, 0xC1, 0x27, 0x80, 0x3F, 0x70, 0x30, 0x61, 0x65, 0x60, 0xDB, 0x50, 0x07, 0x67, 0x72, 0x70, 0x31, 0xC3, 0x3C, 0xA3, 0x31, 0x33, 0x47, 0x72, 0x6F, 0x75, 0x3C, 0x9B, 0x7F, 0xF3, 0x38, 0x67, 0x72, 0x51, 0x07, 0x30, 0x23, 0x34, 0x63, 0x47, 0x5F, 0x41, 0xFC, 0xCF, 0xDF, 0x3F, 0xDB, 0xF1, 0x17, 0xF1, 0xD7, 0x30, 0x5F, 0x3F, 0xEB, 0x47, 0x5F, 0x7E, 0x42, 0xCF, 0x79, 0x3F, 0xF3, 0x00, 0x90, 0x2B, 0xD4, 0xAB, 0x3F, 0xEF, 0xF1, 0x7F, 0x67, 0x6A, 0x72, 0x50, 0xC7, 0x00, 0x72, 0xBF, 0x3C, 0x22, 0xBC, 0x22, 0x00, 0x02, 0xBF, 0xC8, 0xD6, 0x82, 0xBF, 0x3D, 0x7F, 0x07, 0x64, 0xBB, 0x2D, 0x2F, 0xFF, 0x2F, 0x08, 0x00, 0x74, 0x4F, 0x34, 0xA1, 0x32, 0xF3, 0x2F, 0xFF, 0x78, 0x2F, 0xFB, 0x33, 0x64, 0x75, 0x73, 0x62, 0xA1, 0x62, 0xC7, 0x80, 0x10, 0x31, 0xF0, 0x10, 0x32, 0xF0, 0x21, 0x4E, 0x33, 0x62, 0xFA, 0x4C, 0x54, 0x90, 0x3E, 0x30, 0x0B, 0x70, 0x39, 0x4C, 0x0E, 0x54, 0x4D, 0x61, 0x73, 0x3C, 0xCC, 0x63, 0x22, 0x33, 0x1F, 0xA8, 0x0A, 0x06, 0x00, 0x00, 0x0B, 0x2F, 0xFF, 0x38, 0x2F, 0xFF, 0x88, 0xAA, 0x2F, 0xFB, 0x08, 0x2F, 0xF4, 0x88, 0x2F, 0xF8, 0x08, 0x2F, 0xD4, 0x88, 0xAA, 0x2F, 0xD8, 0x4C, 0x2F, 0x10, 0xE8, 0x2F, 0x14, 0xAC, 0x23, 0x74, 0x48, 0x76, 0x05, 0x2F, 0xD7, 0x20, 0x2F, 0x00, 0x35, 0x47, 0xAA, 0x53, 0x4B, 0x00, 0x83, 0x47, 0x02, 0xED, 0x00, 0xA3, 0x47, 0x00, 0x35, 0x57, 0x00, 0xB3, 0x97, 0xD5, 0x20, 0xB3, 0x00, 0xB3, 0x97, 0x40, 0x24, 0x20, 0xA1, 0x30, 0x03, 0x11, 0x2F, 0xFB, 0x74, 0x06, 0x00, 0x04, 0x30, 0x03, 0x87, 0x30, 0x0B, 0x65, 0x06, 0x00, 0x01, 0x30, 0x03, 0x30, 0x17, 0x31, 0x87, 0xA6, 0x5E, 0x03, 0x05, 0x2F, 0x47, 0x4F, 0x5F, 0x31, 0x32, 0x01, 0xB0, 0x7F, 0x01, 0xC1, 0x03, 0xE0, 0x7F, 0xD2, 0xA9, 0x00, 0x00, 0x8C, 0x8C, 0x8C, 0x05, 0xA0, 0x7F, 0xDF, 0x00, 0x16, 0x97, 0x00, 0xF1, 0x7F, 0x03, 0x03, 0xC1, 0x7F, 0x00, 0x16, 0xD7, 0x45, 0x9B, 0x2F, 0xB4, 0x00, 0x25, 0x9B, 0x2C, 0x80, 0x3F, 0x23, 0x44, 0x04, 0x25, 0x97, 0x30, 0x03, 0x06, 0x00, 0x03, 0x06, 0x06, 0x73, 0x09, 0xED, 0xBE, 0x30, 0x03, 0x3F, 0xFB, 0x0D, 0x3A, 0x57, 0xDE, 0x40, 0x30, 0x03, 0xE0, 0x13, 0xC0, 0x30, 0x03, 0xC0, 0x00, 0x75, 0xC7, 0x78, 0x54, 0x10, 0x04, 0x00, 0x01, 0x10, 0x04, 0x28, 0x10, 0x02, 0xA2, 0x37, 0x46, 0xF2, 0x37, 0x26, 0x06, 0x02, 0x3E, 0x05, 0x66, 0x23, 0x33, 0x00, 0x12, 0x43, 0x4D, 0x5F, 0x00, 0x35, 0xAA, 0x00, 0x36, 0x5E, 0x80, 0x58, 0xEA, 0x23, 0x77, 0x05, 0x26, 0x5B, 0x30, 0x03, 0x30, 0x8E, 0xE3, 0x7D, 0xBE, 0x30, 0x03, 0xB0, 0xBF, 0xE0, 0x13, 0xC0, 0xBF, 0x50, 0xA7, 0x00, 0x00, 0xC0, 0xA7, 0xE1, 0x00, 0x21, 0x5F, 0xCF, 0x5F, 0x01, 0xB1, 0x5F, 0x2F, 0xA1, 0xBD, 0xBF, 0x30, 0x03, 0x86, 0x3F, 0xF7, 0xCE, 0x95, 0x17, 0x41, 0x30, 0x03, 0xE0, 0x13, 0xC1, 0xF0, 0x30, 0x03, 0x05, 0x21, 0x5F, 0x00, 0x00, 0xC3, 0x01, 0x31, 0x5F, 0x61, 0x0B, 0xB6, 0xBF, 0xFF, 0x30, 0x03, 0xB0, 0xBF, 0xE0, 0x13, 0xC0, 0xBF, 0x02, 0x61, 0x5F, 0xCD, 0xF7, 0x01, 0xB2, 0xBF, 0x3F, 0xF7, 0xFF, 0x50, 0x03, 0x5D, 0xA7, 0x50, 0x03, 0xC0, 0x13, 0x4F, 0xF7, 0x05, 0x22, 0xBF, 0x00, 0x00, 0xC3, 0x01, 0x32, 0xBF, 0xFF, 0x3F, 0xE3, 0x3F, 0xE7, 0xB0, 0xBF, 0xE0, 0x13, 0xC0, 0xBF, 0x01, 0xF2, 0xBF, 0x03, 0x59, 0x67, 0x57, 0x87, 0xFE, 0x00, 0x59, 0x67, 0x00, 0x1C, 0x63, 0x99, 0x13, 0x40, 0x03, 0x00, 0x79, 0x13, 0x3F, 0x93, 0xC9, 0x67, 0xA0, 0xB1, 0x4E, 0xC7, 0xF5, 0x00, 0x84, 0xD3, 0x70, 0x53, 0x46, 0x31, 0x32, 0x00, 0x63, 0x2F, 0xD0, 0x58, 0x2F, 0xFA, 0x93, 0x05, 0x4F, 0xF1, 0x00, 0x00, 0xCD, 0xCC, 0x4F, 0x4C, 0x28, 0x36, 0x80, 0x3F, 0x50, 0x07, 0x40, 0x0F, 0x4A, 0x8F, 0x50, 0x07, 0xFE, 0x9F, 0xEC, 0xE0, 0x0B, 0x40, 0x03, 0x00, 0x0A, 0x0F, 0x2A, 0xB7, 0x00, 0xA4, 0xB7, 0x60, 0xFB, 0x20, 0xFB, 0x01, 0xC0, 0xA7, 0x27, 0x62, 0x01, 0x00, 0xA7, 0x8A, 0x0F, 0x81, 0x2F, 0x91, 0x00, 0x84, 0xA3, 0x71, 0x83, 0x17, 0x10, 0xF4, 0xBF, 0x01, 0xC1, 0x2F, 0x07, 0x04, 0xD1, 0x2F, 0x00, 0x80, 0xA7, 0x01, 0xF1, 0x2F, 0x7D, 0x08, 0x02, 0x41, 0x2F, 0x00, 0x5D, 0x8B, 0xE1, 0xB7, 0xEB, 0xCB, 0x00, 0xD2, 0x5F, 0x09, 0x04, 0xD2, 0x5F, 0xDE, 0x00, 0xB0, 0xA7, 0x01, 0xC3, 0x07, 0x0A, 0x01, 0xE2, 0x5F, 0x92, 0xE7, 0x00, 0x1F, 0xFB, 0x5F, 0xC7, 0xF8, 0xD6, 0x25, 0x6F, 0x3C, 0xFB, 0xA0, 0x00, 0x68, 0x1F, 0x10, 0x43, 0xE3, 0x00, 0x5C, 0xF7, 0x50, 0x8F, 0x43, 0x83, 0x00, 0x00, 0x44, 0x6C, 0xF7, 0x30, 0x0F, 0x3E, 0x1F, 0x30, 0x0F, 0xCF, 0x2C, 0xF7, 0x6D, 0x77, 0x03, 0x08, 0x6D, 0x77, 0x00, 0xC3, 0x67, 0x00, 0x70, 0x7F, 0x4D, 0x77, 0x5F, 0x41, 0xFE, 0xA3, 0x01, 0x01, 0x4D, 0x77, 0x00, 0x3D, 0xFF, 0x00, 0x1A, 0xEB, 0x01, 0x94, 0xEB, 0x00, 0x10, 0x87, 0xEE, 0x5F, 0xE9, 0x00, 0xED, 0xFF, 0x7E, 0x7F, 0x01, 0x50, 0x7F, 0xFA, 0xEB, 0x02, 0xB0, 0x7F, 0x03, 0xF7, 0x8E, 0x7F, 0x9E, 0x6F, 0xFE, 0x8F, 0x00, 0x02, 0x0F, 0x03, 0x3F, 0x07, 0x00, 0x1A, 0xF3, 0x01, 0x91, 0x8F, 0xEB, 0x00, 0x12, 0x0F, 0x2A, 0x3A, 0x04, 0x8F, 0x07, 0xDC, 0x00, 0x2F, 0x07, 0x0C, 0x4F, 0x07, 0xD6, 0xB7, 0xFF, 0xFD, 0x97, 0xFD, 0x57, 0xFC, 0xE7, 0xFC, 0x77, 0xFC, 0x07, 0xFB, 0x97, 0xFA, 0xE3, 0xFA, 0x57, 0xF7, 0xF9, 0xA3, 0xF9, 0x17, 0xF8, 0x63, 0x3F, 0xE3, 0xCC, 0x00, 0x2F, 0xA7, 0x3E, 0x8F, 0x0A, 0x30, 0xCB, 0x5C, 0x2C, 0x41, 0xA7, 0x43, 0xCF, 0x1B, 0x37, 0x0D, 0xF8, 0x5F, 0x67, 0x72, 0xC1, 0x56, 0xFF, 0x01, 0x48, 0xC3, 0x40, 0x00, 0x78, 0x80, 0x80, 0x34, 0x6F, 0x18, 0x00, 0x00, 0x0A, 0x2B, 0x81, 0x20, 0x0B, 0xEF, 0x80, 0x80, 0x00, 0xEF, 0xEF, 0xFF, 0xF8, 0x0B, 0xBF, 0x70, 0x01, 0x20, 0xFF, 0xF6, 0x8F, 0x85, 0x20, 0x00, 0x88, 0x40, 0x30, 0x83, 0x50, 0x27, 0x1C, 0xCF, 0x00, 0x01, 0x30, 0x20, 0x0B, 0x30, 0x03, 0xC0, 0x38, 0x36, 0x4F, 0x79, 0x87, 0x00, 0x05, 0xFD, 0xFC, 0x0B, 0x61, 0x0A, 0x3F, 0x85, 0x3F, 0x89, 0xFC, 0xFC, 0x0A, 0x0A, 0x30, 0x03, 0x82, 0x2F, 0xFA, 0x83, 0x00, 0x00, 0xF7, 0xF7, 0x3F, 0x10, 0xBF, 0x70, 0xFF, 0x31, 0x7A, 0x20, 0x0B, 0x20, 0x0F, 0xFF, 0x9F, 0xCF, 0xFF, 0x08, 0x1F, 0x2F, 0xF6, 0x60, 0xAF, 0xE5, 0x81, 0x00, 0x00, 0x12, 0xF3, 0xF3, 0x01, 0x22, 0xB0, 0xCF, 0xFF, 0x30, 0x05, 0xF3, 0x41, 0xF3, 0x40, 0x03, 0x28, 0x00, 0x00, 0x5F, 0x5F, 0x40, 0x5F, 0x07, 0x88, 0xFE, 0xCA, 0xFF, 0xCC, 0x30, 0x0B, 0x40, 0x0F, 0x7F, 0xEC, 0x06, 0x88, 0x00, 0x88, 0xFF, 0xCC, 0x2F, 0xCC, 0x30, 0x07, 0xCF, 0x4B, 0xFF, 0x21, 0xEE, 0xFC, 0xFC, 0x30, 0x7D, 0x0C, 0x22, 0xC0, 0x30, 0x03, 0x80, 0x20, 0x1F, 0x06, 0xFF, 0xCC, 0x0D, 0x0A, 0x00, 0x30, 0x0F, 0x00, 0x88, 0x60, 0x60, 0x50, 0xE7, 0x3F, 0xFF, 0x30, 0x0B, 0x40, 0x0F, 0xB2, 0x30, 0x3F, 0xCD, 0x20, 0x37, 0x50, 0x47, 0xCC, 0x02, 0x2D, 0xA7, 0x34, 0x2D, 0xFF, 0x33, 0x41, 0x0F, 0x33, 0x30, 0x07, 0x40, 0x3F, 0x0E, 0x30, 0xC7, 0x5F, 0x84, 0x25, 0xCB, 0xF8, 0x4F, 0xD3, 0x2F, 0x9F, 0x50, 0x0B, 0x20, 0x0F, 0x2F, 0xE8, 0x18, 0xAF, 0xFF, 0x00, 0x30, 0xE7, 0x5F, 0xD7, 0x8E, 0xBF, 0xFF, 0x0A, 0x0E, 0x1E, 0xF7, 0x70, 0x32, 0x64, 0xBF, 0x40, 0xC7, 0x00, 0x09, 0x82, 0x00, 0x00, 0xF4, 0x40, 0xC7, 0x4F, 0x4F, 0x3F, 0xFF, 0xE0, 0x50, 0xD7, 0x30, 0x0B, 0x40, 0x0F, 0x80, 0x00, 0x88, 0xF1, 0xE1, 0x21, 0xFF, 0xEF, 0x70, 0x7F, 0xE1, 0xE1, 0x7F, 0x7F, 0x30, 0x03, 0x80, 0xE0, 0xDF, 0xDC, 0x00, 0x15, 0x00, 0x00, 0xEF, 0xFF, 0x62, 0x05, 0x40, 0x41, 0x3F, 0xDA, 0xD3, 0x40, 0xDF, 0x2E, 0xBE, 0xFD, 0x67, 0xFA, 0x00, 0x0E, 0x0F, 0x2F, 0xB5, 0x07, 0x09, 0x01, 0xAA, 0xBD, 0x21, 0xEB, 0x31, 0xEF, 0x18, 0x01, 0x01, 0x60, 0x25, 0x3F, 0x40, 0x0F, 0xFF, 0x70, 0x00, 0x30, 0xDE, 0x01, 0x30, 0x0B, 0x39, 0x69, 0xFF, 0xF6, 0x1C, 0xCF, 0x00, 0x50, 0x00, 0xFF, 0xF5, 0x30, 0x31, 0xFF, 0xFF, 0x50, 0x5C, 0x46, 0x97, 0x50, 0x5F, 0xBF, 0xF5, 0xFF, 0xFF, 0x40, 0x1C, 0x00, 0xEE, 0x10, 0xF1, 0xEF, 0x41, 0xFF, 0x2F, 0xFF, 0xFC, 0xFD, 0x0C, 0x0A, 0x0B, 0xEB, 0x10, 0x30, 0x88, 0x51, 0xEF, 0x2F, 0x2F, 0x32, 0x00, 0x00, 0x30, 0x03, 0x51, 0xFF, 0xE6, 0x10, 0x30, 0x0F, 0x2E, 0x90, 0x2F, 0xE0, 0xF5, 0x50, 0x30, 0xC7, 0xF5, 0x40, 0x02, 0x1D, 0x1A, 0xF3, 0xF2, 0xDF, 0x20, 0x54, 0x7F, 0xF3, 0xF4, 0x2F, 0x99, 0x00, 0x3B, 0x00, 0xD4, 0x41, 0xFB, 0xB1, 0xEF, 0x32, 0x0B, 0x4E, 0xB6, 0x9A, 0xF1, 0xEF, 0x87, 0x20, 0x79, 0x00, 0x00, 0xEB, 0x10, 0x31, 0xFF, 0x33, 0xE7, 0x00, 0x01, 0xEF, 0x80, 0xB1, 0xFF, 0x00, 0xEE, 0x11, 0xFF, 0x35, 0xFF, 0x33, 0xD0, 0x30, 0xF7, 0x21, 0xF2, 0x33, 0x3F, 0xDF, 0x57, 0xFF, 0x55, 0xFF, 0x05, 0xEE, 0x11, 0xEE, 0x11, 0x55, 0x60, 0x07, 0x06, 0x87, 0x06, 0x81, 0x51, 0xEF, 0x55, 0xFF, 0x04, 0x0D, 0xEE, 0x11, 0x34, 0x41, 0x81, 0x32, 0x0B, 0xE7, 0x10, 0x1E, 0x1E, 0x00, 0x00, 0x30, 0x03, 0x10, 0xF6, 0x60, 0xCF, 0x2E, 0xEE, 0xF6, 0x50, 0x1E, 0x1F, 0x10, 0x00, 0x00, 0x1D, 0xAF, 0xA4, 0x01, 0x1C, 0xF3, 0xF3, 0x65, 0xCF, 0x21, 0x2C, 0x71, 0xEF, 0xF5, 0x50, 0x37, 0xDB, 0xE4, 0x42, 0x0B, 0xD0, 0x30, 0xC7, 0x61, 0xEF, 0x6F, 0x7F, 0xD7, 0xE1, 0xF1, 0xAF, 0xFF, 0x70, 0xD1, 0x20, 0x97, 0x70, 0x7F, 0x9F, 0xEF, 0xF9, 0xFB, 0x10, 0x90, 0x50, 0xFE, 0x20, 0x9D, 0x65, 0x30, 0x9F, 0x01, 0xFB, 0xFF, 0x9F, 0x36, 0x0B, 0x7C, 0x33, 0xB3, 0x2C, 0x6C, 0x06, 0x5B, 0xBA, 0x00, 0x4C, 0xB2, 0x43, 0x02, 0x4C, 0x49, 0x4D, 0xFF, 0xFE, 0x14, 0x2F, 0xFA, 0x02, 0x30, 0x02, 0x28, 0x29, 0xD7, 0x3B, 0x3D, 0x69, 0x6D, 0x61, 0x67, 0x46, 0x10, 0x4C, 0x7C, 0x10, 0x00, 0x0D, 0x62, 0x33, 0x06, 0xD0, 0x01, 0x20, 0x15, 0xA0, 0x00, 0x71, 0x23, 0xDF, 0xFF, 0x33, 0xBF, 0xC0, 0x2E, 0xAB, 0x01, 0xC0, 0xC0, 0xAF, 0x9F, 0x00, 0x00, 0x9F, 0x20, 0x03, 0xE0, 0x73, 0x97, 0x80, 0x07, 0xFF, 0xA0, 0x78, 0x00, 0x02, 0xFF, 0xFC, 0x61, 0x3E, 0x4F, 0x7B, 0x3F, 0xCE, 0x90, 0x90, 0xDF, 0xDF, 0x30, 0x03, 0xF2, 0x01, 0x9D, 0xBF, 0x50, 0x6F, 0x30, 0x6B, 0x40, 0x6F, 0x00, 0xB0, 0x44, 0x93, 0xDF, 0x8F, 0x22, 0x07, 0xD7, 0x00, 0xEE, 0x00, 0x0E, 0xAE, 0x42, 0x17, 0x20, 0x17, 0x70, 0x07, 0xA0, 0x40, 0x6F, 0x80, 0x90, 0x6F, 0xC5, 0xFF, 0xCF, 0x7F, 0xDE, 0x7B, 0x00, 0x95, 0x7D, 0xC1, 0x7F, 0x63, 0x53, 0x71, 0x7F, 0x20, 0x71, 0x7F, 0xC2, 0xCF, 0xAC, 0x06, 0xB1, 0x8B, 0x50, 0xA8, 0x22, 0x70, 0x28, 0x2E, 0x2D, 0xE6, 0x10, 0x00, 0x22, 0x43, 0xFD, 0x3A, 0x8F, 0x76, 0x00, 0x98, 0x6F, 0xA8, 0xCE, 0x42, 0x47, 0x2D, 0x83, 0xFF, 0x7A, 0xFF, 0x45, 0x4F, 0xDE, 0xAA, 0x28, 0x00, 0xBB, 0x4A, 0xAF, 0xBB, 0x50, 0x07, 0xFF, 0x23, 0xEF, 0x84, 0x42, 0xB3, 0xFF, 0x21, 0xFF, 0x53, 0x4F, 0xFE, 0x9A, 0x00, 0x50, 0x68, 0x4A, 0xCF, 0x24, 0x3F, 0xE8, 0xAD, 0xFF, 0xFF, 0xC8, 0xA8, 0x3A, 0xDB, 0xB3, 0x5F, 0xF4, 0xFA, 0x56, 0x77, 0x27, 0xFF, 0x00, 0x7E, 0x4B, 0x85, 0x3F, 0x7B, 0x87, 0x26, 0x8B, 0x2D, 0xED, 0xB3, 0xC2, 0x07, 0xC0, 0x0A, 0x21, 0x1C, 0xF6, 0x22, 0xFF, 0x26, 0xC5, 0x86, 0x4F, 0x7F, 0xDD, 0x22, 0xFF, 0x46, 0x32, 0x4F, 0x5A, 0x43, 0xFF, 0x97, 0x6B, 0xC7, 0x37, 0x3B, 0x10, 0x03, 0xE7, 0xF2, 0xF4, 0xFF, 0xFF, 0xFC, 0x2F, 0x74, 0x30, 0x03, 0xA0, 0x9F, 0x7B, 0xDF, 0xAF, 0x86, 0x0C, 0x09, 0xFF, 0x4F, 0x02, 0x00, 0x00, 0xFF, 0xAD, 0xBF, 0x04, 0x28, 0xFF, 0x00, 0x22, 0x6C, 0x03, 0x07, 0xE0, 0xF8, 0xD6, 0x00, 0xDD, 0x00, 0x48, 0x51, 0xDD, 0xD0, 0x26, 0x03, 0x61, 0xEF, 0x54, 0x00, 0x3C, 0xFD, 0xFF, 0xB8, 0xFF, 0xFE, 0x12, 0x00, 0x00, 0x51, 0x41, 0xEF, 0xFD, 0xA0, 0x97, 0x7F, 0x10, 0x06, 0x00, 0xFE, 0xFC, 0x10, 0xA0, 0x23, 0xF1, 0x6F, 0xE0, 0x2C, 0x01, 0xEF, 0x00, 0x03, 0xFF, 0xFF, 0x1E, 0x8F, 0xA1, 0x1B, 0x50, 0xEF, 0x21, 0x1F, 0xAF, 0x05, 0x94, 0x99, 0xA1, 0xF2, 0x00, 0x00, 0x70, 0xF2, 0x20, 0x03, 0x85, 0x89, 0x40, 0xD7, 0x37, 0xFF, 0x01, 0xBE, 0x88, 0x4D, 0x8F, 0x58, 0x00, 0x23, 0x4F, 0xFF, 0x64, 0xFF, 0xA7, 0x8B, 0x47, 0xE7, 0xDC, 0xFF, 0xED, 0x79, 0x80, 0xDE, 0x28, 0x80, 0x30, 0xD2, 0x22, 0xCC, 0xFF, 0x50, 0xCF, 0x21, 0x00, 0x32, 0x42, 0xDF, 0x33, 0x47, 0x00, 0x26, 0x52, 0x73, 0x30, 0xFB, 0x3F, 0x93, 0x40, 0x04, 0x63, 0x3F, 0x4C, 0x12, 0x38, 0x27, 0x7A, 0xEF, 0x35, 0x94, 0x72, 0xEF, 0x8E, 0xFF, 0x0B, 0xFF, 0x2F, 0x05, 0x4D, 0x2F, 0xAA, 0x6B, 0x03, 0xE4, 0x0C, 0x00, 0xB5, 0xFF, 0x74, 0x40, 0x29, 0xD4, 0x07, 0x55, 0xFF, 0x08, 0xC0, 0x7F, 0x91, 0x4A, 0x8B, 0x99, 0x00, 0x7E, 0x99, 0x5F, 0x97, 0x5A, 0x97, 0x8F, 0xA7, 0x70, 0x17, 0x60, 0x1F, 0x8F, 0xC7, 0x56, 0x1B, 0xFF, 0x55, 0x01, 0x37, 0x97, 0x90, 0x1F, 0x78, 0x4F, 0xE3, 0x27, 0xC0, 0x9B, 0x4A, 0x27, 0x97, 0xFF, 0x2A, 0xA7, 0x27, 0x85, 0x35, 0x26, 0xBF, 0x24, 0x07, 0x88, 0x3F, 0xE7, 0x8B, 0xFF, 0x03, 0x44, 0x10, 0xC6, 0x00, 0xFF, 0x68, 0xD4, 0x80, 0x5F, 0x3F, 0xFF, 0x17, 0x9F, 0xD5, 0xEF, 0xFF, 0x07, 0x66, 0xCF, 0x45, 0x6F, 0x2B, 0x77, 0x3E, 0xEF, 0x3B, 0x7D, 0xAF, 0xF1, 0x30, 0x22, 0x20, 0xFB, 0x5F, 0xEF, 0xF3, 0xF9, 0xF8, 0x90, 0x3F, 0x31, 0x4C, 0xB7, 0x22, 0x97, 0x00, 0x75, 0x85, 0xBF, 0x2F, 0xEA, 0xAF, 0x0D, 0x08, 0xFF, 0x9E, 0xFF, 0x45, 0x4F, 0xE1, 0xA9, 0x00, 0x9A, 0xA2, 0x45, 0xBF, 0x89, 0x55, 0xA7, 0xFF, 0x22, 0xFF, 0x3E, 0x7F, 0x00, 0x0A, 0xFF, 0x75, 0xFF, 0xDA, 0x4F, 0xFF, 0x23, 0x35, 0xB7, 0x5E, 0x83, 0x8A, 0x8F, 0xFF, 0xFF, 0x7F, 0x8F, 0x52, 0x23, 0x0C, 0x0D, 0x92, 0x31, 0xEF, 0xE1, 0xEF, 0xE1, 0xFF, 0x7F, 0xA7, 0x02, 0x2D, 0x07, 0x30, 0x03, 0xF0, 0x0F, 0x01, 0x1D, 0x86, 0x83, 0x45, 0x3E, 0x00, 0xFB, 0xB0, 0xFF, 0xFF, 0x25, 0x13, 0x4C, 0x5F, 0x9D, 0x5F, 0xE8, 0xF2, 0xD0, 0x28, 0x8B, 0x25, 0x31, 0x77, 0x11, 0x0D, 0xA5, 0x1B, 0xC1, 0x96, 0x44, 0x2D, 0x69, 0xFB, 0x01, 0x07, 0xF8, 0xF2, 0x86, 0x45, 0x04, 0x0E, 0x50, 0x00, 0x2F, 0x3F, 0x2C, 0x87, 0xE5, 0xFF, 0x09, 0xFF, 0x20, 0x00, 0xFA, 0x2D, 0xB1, 0x0D, 0x6F, 0x76, 0x87, 0x0E, 0x18, 0xEF, 0x00, 0x38, 0x77, 0x77, 0xC2, 0x5F, 0xAE, 0x2B, 0x6B, 0x1E, 0xFF, 0x01, 0xAF, 0x47, 0xCF, 0x4C, 0x6F, 0x26, 0x89, 0x00, 0x3E, 0x47, 0x3A, 0xE5, 0x0D, 0xB4, 0x2F, 0x04, 0xF1, 0xFF, 0x7F, 0xF1, 0xA0, 0xB0, 0x2C, 0x0D, 0xF4, 0x79, 0x7C, 0x0E, 0x00, 0x60, 0xFB, 0xFF, 0x28, 0x32, 0x00, 0xB0, 0x01, 0x24, 0x07, 0x4F, 0x3C, 0x08, 0x2F, 0x2C, 0x6F, 0x2E, 0xDD, 0xBD, 0xFE, 0xDB, 0x59, 0x00, 0xD8, 0xAD, 0x5E, 0x97, 0xA5, 0x37, 0x87, 0x61, 0x00, 0x17, 0x9F, 0x38, 0x93, 0x40, 0x96, 0x9E, 0xA5, 0x7D, 0xDF, 0xFE, 0x28, 0xAF, 0xD0, 0xE1, 0x39, 0xF1, 0x1A, 0x27, 0x87, 0xD8, 0x2F, 0xF7, 0x2F, 0xE3, 0x3F, 0x2B, 0x55, 0x98, 0xBE, 0x04, 0x07, 0xFF, 0x34, 0xFF, 0x08, 0x4F, 0x09, 0x0E, 0x13, 0xFF, 0x20, 0x4A, 0xBF, 0x22, 0x00, 0x47, 0x22, 0xC3, 0xEF, 0xDE, 0xFF, 0xDD, 0x55, 0x42, 0x60, 0x17, 0x30, 0x1F, 0x80, 0x49, 0x23, 0xFF, 0xED, 0xFF, 0x00, 0x31, 0x00, 0x95, 0xC9, 0x7A, 0xDB, 0x60, 0x37, 0xEE, 0x12, 0x2F, 0x61, 0x50, 0xFD, 0xDA, 0x11, 0x09, 0xFF, 0xBD, 0xFF, 0x69, 0x45, 0xE7, 0x14, 0x6B, 0x9B, 0x0F, 0x0D, 0x8E, 0x5E, 0x01, 0x9F, 0x6C, 0x52, 0x00, 0x1C, 0x2A, 0x35, 0x2E, 0xEF, 0x89, 0x2F, 0x03, 0xAD, 0x00, 0x47, 0x5A, 0x6F, 0xFD, 0x74, 0x4F, 0x9F, 0x1E, 0xB9, 0xFF, 0xDC, 0x4F, 0xFF, 0x28, 0x6C, 0x2B, 0xB2, 0x4F, 0x57, 0xBB, 0x6A, 0xFF, 0x2B, 0xAA, 0x2D, 0x64, 0x10, 0x60, 0xB7, 0x32, 0x35, 0xDC, 0x10, 0x15, 0x00, 0xB4, 0xEC, 0x2F, 0xD7, 0xF9, 0x7B, 0x78, 0xEF, 0x68, 0x9F, 0x10, 0x8B, 0xFF, 0x25, 0xAB, 0x8F, 0x6D, 0xFF, 0x8F, 0x02, 0x5F, 0x00, 0x3F, 0xCD, 0x6C, 0x01, 0xEC, 0xAC, 0xCE, 0x7F, 0x2E, 0xAB, 0xDE, 0x7F, 0x68, 0x7F, 0xC0, 0x9D, 0x2E, 0x04, 0x0E, 0x88, 0xFF, 0xEF, 0xEF, 0x8A, 0xAF, 0x8E, 0x00, 0x47, 0x24, 0xDD, 0x78, 0xDD, 0x77, 0x33, 0x11, 0x01, 0x33, 0x11, 0x8D, 0x7D, 0x13, 0x13, 0x7D, 0x20, 0x03, 0xBF, 0x8A, 0xBF, 0x77, 0x50, 0x17, 0x70, 0x07, 0xFF, 0x49, 0x30, 0x2B, 0xB0, 0x2F, 0xF0, 0x0F, 0xB7, 0x01, 0xB9, 0x7F, 0xA8, 0x6D, 0xEA, 0x7F, 0x7F, 0x10, 0x6F, 0x7F, 0x27, 0xB0, 0x04, 0xA1, 0x00, 0xA0, 0x0D, 0xB0, 0x01, 0x02, 0x60, 0xED, 0x61, 0xFF, 0x2C, 0xFF, 0xBE, 0x35, 0xFF, 0xF0, 0x3E, 0xB7, 0x00, 0xC0, 0xFF, 0x19, 0x00, 0x21, 0x1D, 0x01, 0x28, 0xFA, 0x18, 0xCC, 0xFF, 0x3A, 0x3B, 0x92, 0x40, 0x3F, 0x17, 0xFF, 0x6B, 0x8D, 0x27, 0x4C, 0x84, 0xFF, 0xE9, 0xBD, 0xB9, 0x3C, 0xB8, 0xFD, 0x23, 0x34, 0xE2, 0x30, 0x62, 0x4C, 0xDA, 0x40, 0x13, 0xF7, 0xFF, 0xF1, 0x20, 0x03, 0xEF, 0x08, 0xFF, 0xE8, 0xFF, 0xE0, 0x20, 0x03, 0xE1, 0xFF, 0xD9, 0x38, 0xFF, 0xD3, 0x50, 0x95, 0x2E, 0xE1, 0x21, 0x87, 0x57, 0xFF, 0x86, 0x34, 0xFF, 0xD1, 0x93, 0x69, 0x30, 0x41, 0xFA, 0x31, 0x9F, 0xAC, 0xFF, 0x44, 0xC7, 0x41, 0xA5, 0xD9, 0xFF, 0xE4, 0x50, 0x5B, 0xF6, 0xFF, 0x41, 0xF2, 0x20, 0x5D, 0xFB, 0xFF, 0xEE, 0xFF, 0xEA, 0x2F, 0x23, 0x54, 0xF5, 0x20, 0x05, 0xE4, 0x23, 0x97, 0xEA, 0x2E, 0x2E, 0xDA, 0xFF, 0x10, 0xDB, 0xFF, 0xD5, 0x2C, 0x6E, 0xC6, 0xFF, 0xD0, 0xFF, 0x05, 0xCB, 0xFF, 0xC1, 0xFF, 0xBC, 0x27, 0xE7, 0xE1, 0x20, 0x11, 0x41, 0xD2, 0x24, 0x7A, 0xDA, 0xFF, 0xCD, 0xFF, 0xCA, 0x20, 0x19, 0x04, 0xC1, 0xFF, 0xB7, 0xFF, 0xB3, 0x20, 0xFE, 0xBA, 0xFF, 0x14, 0xAF, 0xFF, 0xAB, 0x05, 0xD1, 0xFF, 0x5F, 0x62, 0x6D, 0x03, 0xFF, 0x51, 0x29, 0x20, 0xC2, 0xC2, 0xE1, 0x7F, 0x05, 0xFF, 0x9F, 0x22, 0x8D, 0x5B, 0x07, 0x21, 0x61, 0xA7, 0x20, 0x9A, 0x5F, 0xE9, 0x8A, 0xD9, 0x48, 0x38, 0x99, 0x50, 0xFE, 0x41, 0x01, 0xF7, 0x25, 0x34, 0xEA, 0xFF, 0xE0, 0x8D, 0xA2, 0xD1, 0x73, 0xF6, 0x80, 0x27, 0xF7, 0xFF, 0xEB, 0x25, 0x56, 0xE0, 0xA8, 0x21, 0x1D, 0xE9, 0x21, 0x25, 0xDE, 0x2F, 0x4A, 0xD4, 0xFF, 0xD3, 0x28, 0xFF, 0xC9, 0x2F, 0x52, 0xD3, 0x2B, 0x3D, 0xC9, 0xFF, 0xC8, 0xA8, 0x25, 0x49, 0xBD, 0x21, 0x07, 0xFC, 0x27, 0x46, 0xF0, 0xFF, 0xE6, 0xA2, 0x20, 0x2D, 0xE2, 0x25, 0x9E, 0xD5, 0xFF, 0xE3, 0x21, 0x95, 0xD6, 0xAA, 0x2D, 0xB0, 0xD0, 0x20, 0x21, 0xC3, 0x25, 0x10, 0xDA, 0x21, 0x3B, 0xCD, 0x28, 0xFF, 0xC5, 0x21, 0x4D, 0xC4, 0x25, 0x7B, 0xB6, 0xFF, 0xBF, 0x80, 0x21, 0x3D, 0xB2, 0xFF, 0xAB, 0xFF, 0xB0, 0xFF, 0xA9, 0x0A, 0xFF, 0xA3, 0xFF, 0x9C, 0x21, 0x51, 0xC0, 0x22, 0x4A, 0xB5, 0xA8, 0x21, 0x53, 0xAE, 0x21, 0xA8, 0xA2, 0x21, 0x59, 0xAA, 0xFF, 0xA8, 0xA0, 0x20, 0xC8, 0xA0, 0x2F, 0xE0, 0x95, 0xFF, 0x8C, 0xFF, 0xA6, 0x80, 0x2B, 0x49, 0x9A, 0xFF, 0x92, 0xFF, 0x96, 0xFF, 0x8F, 0xA8, 0x25, 0x33, 0x84, 0x20, 0x05, 0x87, 0x22, 0x2C, 0x7C, 0xFF, 0x7F, 0x2A, 0xFF, 0x79, 0x2B, 0x43, 0x6E, 0x22, 0x86, 0xB8, 0x20, 0x4B, 0xAA, 0x8C, 0x20, 0x53, 0xAD, 0xFF, 0xA4, 0x21, 0x00, 0x30, 0x53, 0x96, 0xFF, 0x54, 0x90, 0x2B, 0xFF, 0x92, 0x20, 0xFC, 0x85, 0x20, 0x4B, 0xA4, 0xFF, 0x41, 0x9B, 0x20, 0x3D, 0xA0, 0xFF, 0x9D, 0xFF, 0x93, 0x20, 0x17, 0x04, 0x8D, 0xFF, 0x89, 0xFF, 0x80, 0x20, 0x3F, 0x86, 0xFF, 0x50, 0x83, 0x20, 0x41, 0x76, 0x20, 0x0D, 0x83, 0xFF, 0x7D, 0xFF, 0x14, 0x77, 0xFF, 0x7E, 0x20, 0x4F, 0x72, 0x25, 0x87, 0x72, 0xFF, 0x04, 0x6C, 0xFF, 0x67, 0xFF, 0x62, 0x40, 0x03, 0x5C, 0xFF, 0x00, 0x58, 0xFF, 0x74, 0xFF, 0x70, 0xFF, 0x69, 0xFF, 0x50, 0x65, 0x25, 0xA1, 0x6A, 0x20, 0x15, 0x5F, 0xFF, 0x5E, 0xFF, 0x04, 0x5A, 0xFF, 0x53, 0xFF, 0x50, 0x22, 0x6C, 0x54, 0xFF, 0x14, 0x4D, 0xFF, 0x4A, 0x00, 0xD3, 0xFF, 0x16, 0x24, 0x1D, 0x6B, 0xFF, 0x6A, 0x15, 0x22, 0x66, 0x72, 0xD7, 0x85, 0x2F, 0xA8, 0xED, 0x5F, 0x95, 0xF9, 0xAA, 0x2E, 0xCE, 0xF0, 0x94, 0x3F, 0x75, 0x21, 0xBF, 0xD5, 0x84, 0x4D, 0x3D, 0xD5, 0x2F, 0xD0, 0xAF, 0xAC, 0xFD, 0x22, 0xFB, 0xE8, 0x26, 0x3B, 0xE0, 0x2F, 0xE7, 0x55, 0xF8, 0x2F, 0x06, 0xF1, 0x23, 0x03, 0xD9, 0x23, 0x01, 0xD3, 0x21, 0x7F, 0x55, 0xF0, 0x28, 0xC8, 0xE6, 0x21, 0x77, 0xD6, 0x23, 0x0F, 0xCC, 0x22, 0xD1, 0x55, 0xDD, 0x21, 0x89, 0xD5, 0x22, 0xBF, 0xC3, 0x22, 0xF6, 0xBB, 0x22, 0xB1, 0x55, 0xBF, 0x21, 0x61, 0xB5, 0x22, 0xB1, 0xA8, 0x21, 0x59, 0x9F, 0x22, 0xBB, 0x55, 0xAB, 0x21, 0x69, 0xA2, 0x21, 0x5F, 0x95, 0x2D, 0x23, 0x8C, 0x42, 0xD5, 0x5A, 0xD2, 0x21, 0x9F, 0xBF, 0x21, 0x95, 0x30, 0x1B, 0xCB, 0x27, 0x21, 0xC4, 0xAA, 0x21, 0xA7, 0xB0, 0x21, 0x9D, 0xA9, 0x21, 0x9F, 0xA6, 0x21, 0x7D, 0x9E, 0xAB, 0x21, 0x7F, 0x8F, 0x23, 0xA2, 0x87, 0x21, 0x77, 0x96, 0x26, 0xB9, 0x30, 0x0B, 0x51, 0x7F, 0x21, 0x19, 0x78, 0x21, 0x7F, 0x9E, 0xFF, 0x94, 0x20, 0x01, 0x45, 0x8A, 0x26, 0xCF, 0x82, 0xFF, 0x81, 0x20, 0x11, 0x8B, 0x20, 0x05, 0x62, 0x82, 0x20, 0x19, 0x30, 0x1B, 0x6E, 0xFF, 0x66, 0x21, 0xA5, 0x71, 0xA2, 0x21, 0x41, 0x68, 0x21, 0x3D, 0x63, 0xFF, 0x60, 0x21, 0x3B, 0x66, 0xA0, 0x21, 0x41, 0x5E, 0x2D, 0xBD, 0x57, 0xFF, 0x51, 0xFF, 0x4F, 0x2A, 0xFF, 0x48, 0x21, 0xC5, 0x70, 0x20, 0x21, 0x68, 0x80, 0x17, 0x6A, 0xAA, 0x20, 0x25, 0x63, 0x21, 0x63, 0x57, 0x20, 0x1D, 0x50, 0x20, 0x1F, 0x55, 0x20, 0xFF, 0x4E, 0x20, 0x01, 0x46, 0xFF, 0x47, 0xFF, 0x40, 0x0A, 0xFF, 0x3F, 0xFF, 0x39, 0x20, 0x07, 0x3F, 0x20, 0x09, 0x39, 0xA2, 0x20, 0x09, 0x32, 0x20, 0x01, 0x2C, 0xFF, 0x5D, 0x23, 0xF6, 0x53, 0xC0, 0x20, 0x23, 0x30, 0x03, 0x49, 0xFF, 0x44, 0xFF, 0x4B, 0xFF, 0x10, 0x45, 0xFF, 0x42, 0x21, 0x3E, 0x40, 0xFF, 0x3C, 0xFF, 0x05, 0x38, 0xFF, 0x34, 0xFF, 0x4A, 0x20, 0x39, 0x41, 0x21, 0x4E, 0x50, 0x43, 0x20, 0x05, 0x3B, 0x20, 0x11, 0x38, 0xFF, 0x35, 0xFF, 0x00, 0x31, 0xFF, 0x2E, 0xFF, 0x33, 0xFF, 0x30, 0xFF, 0x55, 0x2B, 0x23, 0x46, 0x3B, 0x20, 0x0F, 0x33, 0x20, 0x0F, 0x30, 0x24, 0xD2, 0x05, 0x2A, 0xFF, 0x26, 0xFF, 0x2D, 0x2B, 0x94, 0x27, 0x2D, 0xA5, 0x01, 0x23, 0xFF, 0x20, 0xFF, 0x1E, 0xFF, 0x1B, 0x23, 0x68, 0x50, 0x26, 0x40, 0x0B, 0x24, 0x2D, 0xB9, 0x1E, 0xFF, 0x1C, 0xFF, 0x05, 0x1D, 0xFF, 0x1A, 0xFF, 0x18, 0x21, 0xD2, 0x18, 0x24, 0xB8, 0x15, 0x13, 0xFF, 0x12, 0x33, 0x8B, 0x00, 0x20, 0x36, 0xD2, 0x6B, 0xF6, 0xB5, 0x34, 0x85, 0x00, 0x24, 0x87, 0x64, 0xB3, 0xFA, 0x2C, 0x0B, 0xEA, 0x24, 0x61, 0x55, 0xE4, 0x24, 0x57, 0xCC, 0x24, 0x59, 0xC6, 0x27, 0xFF, 0xDF, 0x24, 0x75, 0x52, 0xDA, 0x24, 0x5F, 0xC1, 0x24, 0x4D, 0xBC, 0x00, 0x22, 0xB6, 0x00, 0xC5, 0x23, 0x56, 0x43, 0x7B, 0xFE, 0xFF, 0xF2, 0x34, 0xA5, 0x00, 0x23, 0x4E, 0xAA, 0x24, 0xFD, 0xED, 0x2A, 0x35, 0xEA, 0x2C, 0x67, 0xD5, 0x24, 0xE9, 0xD2, 0xAA, 0x24, 0x91, 0xB7, 0x24, 0x8F, 0xB2, 0x29, 0x02, 0xCD, 0x24, 0xA5, 0xCA, 0xAA, 0x25, 0x7E, 0xAF, 0x24, 0x81, 0xAB, 0x25, 0x86, 0xB0, 0x23, 0x01, 0xAA, 0xAA, 0x23, 0x4B, 0x96, 0x23, 0x4D, 0x90, 0x23, 0x5B, 0xA4, 0x23, 0x09, 0x9F, 0xAA, 0x2E, 0xFF, 0x8A, 0x23, 0x35, 0x85, 0x22, 0xED, 0x7D, 0x22, 0xE9, 0x77, 0xAA, 0x22, 0xDB, 0x67, 0x22, 0xD9, 0x62, 0x22, 0xE7, 0x72, 0x23, 0x39, 0x6D, 0xAA, 0x22, 0xE3, 0x5C, 0x22, 0xE5, 0x57, 0x23, 0x6B, 0x9A, 0x23, 0x37, 0x96, 0xAA, 0x23, 0x17, 0x80, 0x23, 0x19, 0x7C, 0x23, 0x77, 0x93, 0x23, 0x29, 0x90, 0xAA, 0x25, 0x4A, 0x79, 0x23, 0x21, 0x76, 0x22, 0xFF, 0x6A, 0x23, 0x01, 0x65, 0xAA, 0x24, 0x7A, 0x53, 0x22, 0xF9, 0x50, 0x28, 0xA9, 0x62, 0x23, 0x09, 0x5F, 0xAA, 0x25, 0x6C, 0x4D, 0x23, 0x01, 0x4A, 0x21, 0x7F, 0x53, 0x25, 0x78, 0x4E, 0xA2, 0x21, 0x77, 0x42, 0x21, 0x79, 0x3D, 0xFF, 0x52, 0x21, 0x85, 0x4E, 0xAA, 0x21, 0x87, 0x40, 0x21, 0x7D, 0x3C, 0x21, 0x7F, 0x3A, 0x21, 0x69, 0x35, 0xAA, 0x21, 0x6F, 0x2D, 0x25, 0xA4, 0x28, 0x2E, 0xFD, 0x30, 0x21, 0x65, 0x2C, 0xAA, 0x41, 0x53, 0x1E, 0x21, 0x61, 0x1B, 0x21, 0x9F, 0x41, 0x21, 0xDD, 0x3D, 0xAA, 0x21, 0xAB, 0x31, 0x21, 0x99, 0x2D, 0x21, 0xA7, 0x3B, 0x21, 0xAF, 0x38, 0xAA, 0x21, 0x9F, 0x2B, 0x21, 0xA1, 0x29, 0x24, 0xE8, 0x23, 0x21, 0x95, 0x20, 0xAA, 0x21, 0x77, 0x18, 0x21, 0x79, 0x15, 0x21, 0x87, 0x1E, 0x2F, 0x43, 0x1C, 0xAA, 0x21, 0x83, 0x13, 0x23, 0x5E, 0x12, 0x2F, 0x4F, 0x1D, 0x40, 0x1B, 0x19, 0x8A, 0x23, 0x6C, 0x14, 0xFF, 0x11, 0x26, 0x72, 0x14, 0x23, 0x76, 0x11, 0xA8, 0x20, 0x09, 0x0E, 0x20, 0x01, 0x0B, 0x21, 0xA3, 0x10, 0xFF, 0x0F, 0x20, 0xFF, 0x0D, 0x40, 0x03, 0x0B, 0xFF, 0x0A, 0xFF, 0x0C, 0xAA, 0x20, 0x03, 0x09, 0x25, 0x24, 0x08, 0x25, 0x28, 0x06, 0x25, 0x32, 0x13, 0xAA, 0x20, 0x1D, 0x10, 0x20, 0x1F, 0x0C, 0x20, 0x15, 0x0A, 0x25, 0x3C, 0x0F, 0xAB, 0x20, 0x33, 0x0D, 0x20, 0x27, 0x08, 0x20, 0x1D, 0x07, 0x25, 0x52, 0x50, 0x25, 0x56, 0x04, 0x20, 0x01, 0x03, 0x25, 0x76, 0x02, 0x80, 0x07, 0x50, 0x01, 0x01, 0xAC, 0x00, 0xB9, 0x7F, 0x20, 0x2C, 0x1D, 0x03, 0x04, 0xE9, 0x7F, 0x10, 0x04, 0x80, 0x59, 0x30, 0xC2, 0x30, 0xFE, 0xE2, 0x2C, 0x3A, 0x3A, 0x46, 0x20, 0xF8, 0xE9, 0xFF, 0x0C, 0x00, 0x95, 0x00, 0xDC, 0x00, 0x3E, 0x2E, 0x03, 0x1F, 0xA9, 0x80, 0xF2, 0x18, 0x00, 0x10, 0xF9, 0x38, 0xEF, 0x4F, 0x02, 0x50, 0x90, 0xFF, 0x1F, 0xFF, 0xC0, 0xD0, 0x00, 0xDE, 0x98, 0xBF, 0x1B, 0xCB, 0xFF, 0x2F, 0x23, 0xF2, 0x7F, 0xE0, 0x4B, 0xFF, 0x01, 0xCF, 0x27, 0x10, 0x3A, 0x60, 0x2B, 0x20, 0x01, 0x1C, 0x20, 0x20, 0x22, 0x1E, 0x1D, 0x80, 0x0E, 0x20, 0x1D, 0x0D, 0x20, 0x0F, 0xCE, 0xA2, 0x25, 0xBE, 0xB0, 0x25, 0xCC, 0xA0, 0x00, 0x04, 0x27, 0x9B, 0x03, 0x00, 0x20, 0xCA, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0xCC, 0x00, 0xC0, 0xA3, 0x74, 0xA4, 0x0B, 0x05, 0x84, 0x14, 0x21, 0x0A, 0xBB, 0x3F, 0xFF, 0x01, 0x6C, 0x00, 0x90, 0x3F, 0xFF, 0x00, 0x12, 0xBB, 0x00, 0x06, 0x20, 0x00, 0xA5, 0xC9, 0x00, 0x20, 0x7B, 0xB6, 0xA0, 0x30, 0xAA, 0x1E, 0x18, 0x08, 0x00, 0xBA, 0x04, 0x09, 0x4F, 0xFF, 0xBA, 0x02, 0xDB, 0x80, 0x4F, 0xFF, 0x12, 0x20, 0xAB, 0x6C, 0x3C, 0x90, 0x70, 0x00, 0x4C, 0x3B, 0x80, 0x70, 0x38, 0x09, 0x2E, 0xB6, 0x0A, 0x29, 0x28, 0x03, 0xAC, 0x40, 0x3F, 0x4C, 0x90, 0x3F, 0x11, 0x00, 0x2B, 0xA6, 0xC9, 0xB8, 0x6C, 0xA6, 0xA0, 0x40, 0x02, 0xAA, 0x2E, 0x48, 0x00, 0xBA, 0x24, 0x30, 0x3F, 0x70, 0x0A, 0x10, 0xD5, 0x82, 0xDB, 0x38, 0x03, 0x09, 0x28, 0x1F, 0x3D, 0x00, 0x0C, 0x90, 0x60, 0x2E, 0xC7, 0xA0, 0xCA, 0x09, 0x90, 0x20, 0x59, 0x09, 0x07, 0x26, 0x5C, 0xC1, 0x00, 0x00, 0xD1, 0x20, 0xE1, 0x21, 0x40, 0x87, 0x00, 0x0B, 0x01, 0x6A, 0xE1, 0x00, 0xC1, 0x03, 0x00, 0xE1, 0xC1, 0x02, 0xAA, 0x7B, 0x02, 0xA7, 0xC4, 0xD0, 0x8B, 0x1C, 0x70, 0x58, 0x38, 0x50, 0x20, 0x00, 0x0A, 0x78, 0x41, 0xA0, 0xC5, 0x06, 0x01, 0xAE, 0x54, 0x5F, 0x10, 0x00, 0x38, 0x4F, 0x11, 0x99, 0x64, 0x10, 0x60, 0x0C, 0x11, 0x00, 0x5D, 0x11, 0x90, 0x15, 0x20, 0xB0, 0x2A, 0x80, 0x1F, 0x77, 0x1A, 0x22, 0xD0, 0x4A, 0xED, 0x80, 0x3F, 0xA8, 0x10, 0x02, 0x40, 0x3F, 0x20, 0x00, 0x37, 0x7C, 0xC0, 0x5F, 0x31, 0x6A, 0x1C, 0x27, 0x51, 0xC5, 0x00, 0x30, 0x9F, 0x1E, 0x05, 0x00, 0x40, 0xEA, 0x70, 0xDF, 0x3A, 0x6E, 0xA0, 0x0C, 0xBA, 0x5C, 0x40, 0x41, 0xCD, 0x30, 0xE3, 0xFF, 0x20, 0xF9, 0x00, 0xB7, 0xFF, 0xFF, 0xAF, 0xCF, 0x03, 0xD1, 0xF8, 0x01, 0xFF, 0x7F, 0xFE, 0xFF, 0x0C, 0x05, 0x06, 0x33, 0x15, 0x00, 0x00, 0x90, 0x80, 0xED, 0xFF, 0xEE, 0xFF, 0x79, 0x0A, 0x00, 0x77, 0x00, 0xEE, 0x20, 0x07, 0x77, 0x20, 0x07, 0x00, 0x01, 0xAA, 0x00, 0x07, 0xFF, 0xFF, 0x3F, 0xCF, 0x2B, 0x90, 0x06, 0xA5, 0x00, 0x00, 0xF9, 0xF8, 0x70, 0x17, 0x80, 0x1F, 0x4A, 0x00, 0x00, 0xA0, 0x6F, 0x6F, 0xF0, 0x30, 0x00, 0x9B, 0x07, 0x00, 0x00, 0xEF, 0x23, 0x00, 0x80, 0x37, 0x80, 0x3F, 0xEA, 0x05, 0x8B, 0x00, 0x30, 0x1F, 0x80, 0xE8, 0xAB, 0x59, 0xF7, 0x59, 0x00, 0x60, 0x3F, 0x3B, 0xFC, 0xE0, 0x6B, 0xF2, 0x00, 0xE0, 0x5F, 0x00, 0x90, 0x7F, 0xA2, 0x00, 0x6A, 0xF4, 0xF3, 0x2A, 0x9F, 0x8F, 0x90, 0xBF, 0xDE, 0x20, 0xDF, 0x97, 0xDC, 0x48, 0x01, 0x00, 0x20, 0x10, 0x7B, 0xFF, 0x02, 0xAF, 0xFC, 0x30, 0x24, 0xFF, 0xFA, 0x39, 0xE3, 0x4E, 0xFF, 0x24, 0xE5, 0x65, 0x50, 0x00, 0x01, 0xA9, 0x88, 0x05, 0x04, 0xFF, 0xF6, 0x1E, 0x0B, 0x8F, 0xB0, 0x50, 0xEF, 0x00, 0x4A, 0x9F, 0x01, 0x00, 0x32, 0x53, 0x07, 0x0C, 0xA2, 0x5C, 0x70, 0x25, 0x83, 0x90, 0x64, 0xF0, 0x41, 0xFA, 0x41, 0x45, 0xFF, 0xEF, 0x32, 0x02, 0x00, 0x20, 0xC5, 0x2A, 0xD9, 0x80, 0x80, 0x30, 0x03, 0xFF, 0x02, 0xFE, 0x05, 0x0B, 0xF8, 0xE1, 0x6F, 0x2B, 0x97, 0x80, 0x04, 0x90, 0x00, 0x05, 0x60, 0x00, 0x2F, 0x66, 0xB6, 0xFF, 0x00, 0xFF, 0x25, 0x06, 0x06, 0x1F, 0xF8, 0xF8, 0x9F, 0x22, 0xF8, 0xF7, 0x2F, 0x73, 0x06, 0x07, 0xBB, 0x25, 0xEC, 0xD0, 0x40, 0x40, 0x3B, 0xBB, 0xB8, 0x00, 0x6F, 0x6F, 0x70, 0xF0, 0x00, 0x6F, 0x6F, 0xE0, 0xE0, 0x68, 0xDF, 0x50, 0xA0, 0x08, 0xDF, 0xDF, 0x90, 0x90, 0x20, 0x0B, 0xF0, 0x4B, 0x00, 0x20, 0xB0, 0x00, 0x20, 0x0B, 0xA0, 0x9B, 0x00, 0x70, 0x00, 0x00, 0x89, 0xFF, 0xB6, 0x8D, 0xFF, 0xFF, 0x04, 0x03, 0x00, 0xAD, 0xFD, 0x23, 0x2F, 0xF3, 0xF3, 0x9F, 0xAF, 0x90, 0x20, 0x0B, 0x04, 0xBB, 0x2D, 0xB5, 0xF3, 0xF3, 0xAF, 0xBF, 0x00, 0xB2, 0x00, 0x8B, 0x00, 0xE8, 0xB0, 0xFF, 0xEF, 0x00, 0xC0, 0xC0, 0xFF, 0xFF, 0x49, 0x10, 0x81, 0xFD, 0x30, 0x90, 0xC1, 0x2B, 0x9B, 0x20, 0x0B, 0x90, 0x00, 0xBB, 0x00, 0x00, 0xA0, 0x21, 0xFF, 0xFF, 0x01, 0x00, 0xB3, 0x00, 0x00, 0xCC, 0x07, 0x7C, 0xFA, 0x68, 0xAC, 0xFB, 0x89, 0x00, 0x00, 0x0A, 0x95, 0xFA, 0x5F, 0x48, 0xF8, 0xF9, 0x00, 0x03, 0x06, 0x72, 0xFA, 0xBD, 0x21, 0x9D, 0x01, 0x00, 0x17, 0x0D, 0xF9, 0xF9, 0x01, 0x00, 0xB7, 0x00, 0x00, 0x58, 0xDF, 0xDB, 0xD8, 0x4F, 0x3F, 0x30, 0x20, 0x00, 0x3A, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x38, 0x6A, 0x04, 0x4F, 0x4F, 0x20, 0x30, 0x3B, 0x2E, 0x19, 0xFF, 0xFF, 0x10, 0x4A, 0x0B, 0xBB, 0x2E, 0x18, 0x70, 0xFA, 0xCC, 0x5E, 0x00, 0xFF, 0xFF, 0x09, 0x08, 0xFA, 0xFA, 0x8F, 0x8F, 0x00, 0xF3, 0xF3, 0x8F, 0x7F, 0xFF, 0xFC, 0x08, 0x3D, 0x00, 0x91, 0x00, 0xDD, 0x00, 0xF3, 0xF9, 0x8F, 0x9F, 0x00, 0xBA, 0x00, 0x6B, 0x00, 0x00, 0xB0, 0xC7, 0xAF, 0x00, 0xF4, 0xF7, 0x6F, 0x7F, 0xDC, 0x70, 0x19, 0xDF, 0x00, 0x30, 0x30, 0xFF, 0xFF, 0xF5, 0xC0, 0x6F, 0x9F, 0x00, 0x10, 0x00, 0xD8, 0x00, 0x30, 0x60, 0xFF, 0xEF, 0x04, 0xDB, 0x12, 0x2A, 0x00, 0x31, 0x2E, 0x70, 0x09, 0x0C, 0x80, 0x34, 0xF2, 0xFF, 0xFE, 0x00, 0x10, 0xFD, 0xFF, 0x09, 0x88, 0x5B, 0xEB, 0x40, 0x40, 0xB0, 0x20, 0x2B, 0xFF, 0x9F, 0x1E, 0x68, 0x08, 0x36, 0x67, 0xAE, 0x7F, 0x05, 0x09, 0xE4, 0x31, 0x40, 0x00, 0xFF, 0x40, 0xE4, 0x3F, 0x49, 0x9F, 0xFF, 0x02, 0xBF, 0xFA, 0x30, 0x3B, 0xFF, 0xC8, 0x00, 0x0F, 0x49, 0x23, 0xFC, 0x24, 0x02, 0xEE, 0x24, 0x02, 0x40, 0x07, 0xFD, 0xA5, 0xFA, 0x5F, 0x74, 0x60, 0x17, 0x70, 0x1F, 0x00, 0x05, 0xDA, 0x09, 0x90, 0x1F, 0x87, 0xD0, 0xBF, 0x80, 0x55, 0xFA, 0x20, 0xFB, 0xF9, 0xFF, 0xFF, 0x8C, 0xAF, 0x08, 0x03, 0xFF, 0x5E, 0x04, 0x10, 0x16, 0x4D, 0xE6, 0x43, 0x4C, 0x49, 0x08, 0x4D, 0xFF, 0xFE, 0x14, 0x2F, 0xFF, 0x02, 0x02, 0x28, 0xC2, 0x26, 0xF7, 0x38, 0x90, 0x69, 0x6D, 0x61, 0x67, 0x37, 0x02, 0x80, 0xA0, 0x27, 0xBE, 0x0D, 0x67, 0x0F, 0x4A, 0x4A, 0xE3, 0x64, 0xDB, 0x00, 0xE2, 0x95, 0x36, 0xB4, 0xC5, 0xE8, 0xC1, 0x17, 0x00, 0xED, 0xFB, 0xAB, 0x9B, 0x18, 0xC3, 0x05, 0x24, 0x00, 0xB5, 0x7C, 0x77, 0xB7, 0xD1, 0x53, 0x44, 0x24, 0x00, 0xD2, 0xBC, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char Nintendo_DistributedBy_LZ[0x2000] =
+{
+ 0x11, 0x48, 0x65, 0x00, 0x00, 0x64, 0x61, 0x72, 0x63, 0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x28, 0x65, 0x00, 0x00, 0x83, 0x30, 0x09, 0x38, 0x04, 0x00, 0x00, 0x60, 0x20, 0x03, 0x30, 0x13, 0xAB, 0x30, 0x18, 0x15, 0x20, 0x1D, 0x02, 0xA0, 0x0B, 0x06, 0x20, 0x2B, 0x30, 0x18, 0x5A, 0x09, 0x20, 0x35, 0x10, 0x20, 0x39, 0x30, 0x2B, 0xF8, 0x20, 0x41, 0x54, 0x85, 0x30, 0x0B, 0x05, 0x00, 0x00, 0xEC, 0x20, 0x4D, 0x98, 0x30, 0x17, 0xD0, 0x20, 0x28, 0x30, 0x17, 0xDC, 0x30, 0x23, 0x07, 0x00, 0x00, 0xCC, 0x09, 0x0C, 0x00, 0x00, 0x20, 0x20, 0x51, 0x40, 0x14, 0x20, 0x2B, 0xA0, 0x20, 0x0B, 0x64, 0x20, 0x5D, 0xA0, 0x20, 0x00, 0x00, 0x4C, 0x99, 0x20, 0x5C, 0xA8, 0x01, 0x50, 0x53, 0x20, 0x22, 0x00, 0xB2, 0x30, 0x75, 0x0A, 0x23, 0x00, 0x00, 0xB4, 0x20, 0x74, 0xE2, 0x20, 0x81, 0xC0, 0x09, 0x25, 0x00, 0x00, 0x3C, 0x20, 0x68, 0x12, 0x02, 0x50, 0x77, 0xA0, 0x30, 0x8F, 0x1C, 0x20, 0x90, 0x00, 0x36, 0x00, 0x00, 0x28, 0xA6, 0x20, 0xAB, 0x3E, 0x20, 0x9C, 0x80, 0x3A, 0x20, 0x0B, 0x20, 0xAD, 0x60, 0xAA, 0x30, 0x17, 0x3C, 0x50, 0x17, 0x82, 0x30, 0x17, 0x40, 0x20, 0x23, 0x08, 0x16, 0x00, 0x00, 0xA4, 0x30, 0x2F, 0x49, 0x20, 0x67, 0x20, 0xE9, 0xC4, 0xAB, 0x30, 0x3B, 0x4A, 0x50, 0x17, 0xDC, 0x30, 0x3B, 0x52, 0x20, 0x47, 0x20, 0xE0, 0x59, 0xF4, 0x30, 0x53, 0x55, 0x20, 0x53, 0x30, 0xD4, 0x00, 0x2E, 0x21, 0x13, 0x01, 0x61, 0x00, 0x6E, 0x00, 0x69, 0x00, 0x6D, 0x21, 0x1D, 0x41, 0x4E, 0x20, 0x07, 0x6E, 0x00, 0x74, 0x00, 0x65, 0x20, 0x11, 0x05, 0x64, 0x00, 0x6F, 0x00, 0x4C, 0x20, 0x03, 0x67, 0x20, 0x07, 0x14, 0x5F, 0x00, 0x44, 0x20, 0x03, 0x30, 0x20, 0x01, 0x5F, 0x00, 0x10, 0x53, 0x00, 0x63, 0x40, 0x1F, 0x65, 0x00, 0x4F, 0x00, 0x55, 0x75, 0x20, 0x2B, 0x41, 0x20, 0x43, 0x62, 0x20, 0x13, 0x6C, 0x40, 0x47, 0xAB, 0x02, 0x50, 0x43, 0x42, 0x03, 0x20, 0x43, 0x43, 0x01, 0x80, 0x87, 0x55, 0x03, 0x20, 0xCB, 0x00, 0x90, 0x43, 0xEB, 0x01, 0x90, 0xCB, 0x00, 0x90, 0x87, 0xF0, 0xCB, 0x62, 0x21, 0x5D, 0x79, 0x21, 0x97, 0x01, 0x31, 0xA1, 0xF5, 0x71, 0x8D, 0x00, 0xF0, 0x2F, 0x71, 0x05, 0xD0, 0x2F, 0x74, 0x42, 0x09, 0x67, 0x23, 0x29, 0x5E, 0x33, 0x22, 0x01, 0x73, 0xA2, 0x01, 0xB0, 0x5B, 0x52, 0x2D, 0x00, 0x10, 0x21, 0x31, 0xAA, 0x01, 0x00, 0x21, 0x32, 0x01, 0x00, 0x43, 0x33, 0xE0, 0x65, 0x4C, 0x23, 0x71, 0x4D, 0x8F, 0x22, 0xA3, 0x73, 0x00, 0x6B, 0x00, 0x40, 0x85, 0x30, 0x1F, 0x00, 0xB0, 0x17, 0xF0, 0x93, 0xD1, 0xF2, 0xE3, 0x32, 0xDB, 0x69, 0x20, 0xE9, 0x74, 0x00, 0x72, 0x23, 0x05, 0x55, 0x62, 0x42, 0xD3, 0x65, 0x22, 0xFD, 0x42, 0x21, 0x71, 0x5F, 0x20, 0xD1, 0x05, 0x32, 0x00, 0x38, 0x00, 0x78, 0x23, 0x84, 0x34, 0xE0, 0xFD, 0x81, 0xB0, 0x02, 0x43, 0x4C, 0x41, 0x4E, 0xFF, 0xFE, 0x23, 0xF0, 0x18, 0x00, 0x02, 0x02, 0x34, 0x23, 0x33, 0xB6, 0x70, 0x61, 0x74, 0x74, 0x31, 0x23, 0xA2, 0x44, 0x5E, 0x34, 0x79, 0x28, 0x33, 0x93, 0xFF, 0xFF, 0x40, 0xFF, 0x34, 0x6C, 0x53, 0x63, 0x65, 0x6E, 0x65, 0x4F, 0x10, 0x75, 0x74, 0x41, 0x24, 0x91, 0x47, 0x5F, 0x41, 0x5F, 0x21, 0x30, 0x30, 0xD0, 0x50, 0x70, 0x61, 0x69, 0x31, 0x33, 0xC3, 0x9A, 0x50, 0x3F, 0x02, 0x00, 0x30, 0x59, 0x34, 0xBD, 0x68, 0x24, 0xC1, 0x50, 0x00, 0x5F, 0x4E, 0x69, 0x6E, 0x4C, 0x6F, 0x67, 0x6F, 0xE1, 0xA0, 0x35, 0x34, 0xC0, 0x34, 0xDD, 0x43, 0x4C, 0x56, 0x43, 0x74, 0x5F, 0x1E, 0x00, 0x10, 0x02, 0x40, 0x87, 0x40, 0x0B, 0xD0, 0x5D, 0x20, 0x76, 0x7F, 0x40, 0x43, 0x35, 0x0C, 0x4E, 0x5F, 0x52, 0x6F, 0x6F, 0x74, 0xE7, 0xD0, 0x7E, 0x00, 0x70, 0x4B, 0x80, 0x57, 0x00, 0x20, 0x20, 0x3B, 0x50, 0x3F, 0x00, 0x30, 0xFF, 0xF1, 0x35, 0x17, 0xB0, 0xFF, 0x24, 0xF2, 0x80, 0xFF, 0x00, 0x00, 0x1E, 0x45, 0x6C, 0xAB, 0x70, 0xFF, 0x42, 0x40, 0xFF, 0x42, 0x00, 0x40, 0xFF, 0x9C, 0x80, 0x2D, 0x90, 0xFF, 0x65, 0x5C, 0x01, 0xE0, 0xFF, 0x90, 0xB3, 0x34, 0xC2, 0x02, 0xD0, 0xF3, 0xC8, 0x20, 0xAA, 0xF7, 0xD0, 0xF3, 0x01, 0x71, 0xFF, 0x31, 0x39, 0x71, 0xFF, 0x65, 0x23, 0x51, 0xB1, 0xFF, 0x31, 0x84, 0x16, 0x47, 0x5F, 0x43, 0x00, 0x81, 0xFF, 0x0F, 0xE1, 0xFF, 0x02, 0x90, 0xFF, 0x12, 0x65, 0xC3, 0x02, 0x31, 0xF3, 0x92, 0x3F, 0x80, 0xBF, 0x91, 0xF3, 0x60, 0x32, 0xB6, 0xED, 0x00, 0x82, 0xFF, 0x36, 0xFF, 0x03, 0x32, 0xFF, 0x7C, 0x27, 0x47, 0x53, 0x3F, 0x0D, 0x42, 0xFF, 0x55, 0x48, 0x27, 0xBD, 0xB0, 0x27, 0xC1, 0xA4, 0x27, 0xAD, 0x24, 0x27, 0xA8, 0x82, 0x36, 0xEB, 0x30, 0x03, 0x00, 0x00, 0xBC, 0x20, 0x03, 0x24, 0xB4, 0x27, 0xCB, 0x88, 0x37, 0x93, 0x27, 0xB4, 0xB0, 0x27, 0x07, 0x74, 0x0A, 0x0B, 0x00, 0x00, 0x78, 0x0B, 0x32, 0xDF, 0x57, 0x00, 0x03, 0x5B, 0x37, 0x52, 0xE5, 0x27, 0x8E, 0x26, 0xD1, 0x33, 0xB7, 0x50, 0x41, 0x83, 0x2F, 0x02, 0xF2, 0xE3, 0xC5, 0x73, 0xDB, 0x01, 0x13, 0x07, 0x50, 0x5F, 0x33, 0x00, 0x80, 0x67, 0xB8, 0x60, 0x67, 0xDD, 0x20, 0xAA, 0x43, 0xC7, 0x38, 0x63, 0xC7, 0x30, 0x6F, 0x93, 0x9F, 0xA0, 0x24, 0x0A, 0x4C, 0xA0, 0x27, 0xC5, 0x80, 0xBE, 0x24, 0x39, 0x23, 0x16, 0xA0, 0xC0, 0x8C, 0x48, 0x99, 0x06, 0x02, 0x00, 0x30, 0x37, 0x70, 0x23, 0x33, 0x33, 0x02, 0xB3, 0x3F, 0xFC, 0x2D, 0xEC, 0xBC, 0x70, 0x0B, 0x0A, 0x32, 0xD7, 0x23, 0x20, 0x0B, 0x30, 0x2F, 0x80, 0x3F, 0x48, 0xC9, 0x07, 0xF1, 0x01, 0xD0, 0x2F, 0xF4, 0x2F, 0xB0, 0x6B, 0x39, 0x2C, 0x40, 0x9D, 0x1C, 0x30, 0x97, 0xBF, 0x61, 0xEF, 0xCC, 0x28, 0x65, 0x30, 0x9B, 0x70, 0xF3, 0x24, 0x87, 0xE4, 0xB9, 0x71, 0x5B, 0x70, 0x50, 0xF1, 0x5B, 0x29, 0x59, 0xD4, 0x8B, 0x80, 0x41, 0xCD, 0xCC, 0x5F, 0xCC, 0x20, 0xEB, 0x20, 0x34, 0x02, 0x00, 0x41, 0x67, 0x00, 0x14, 0xBB, 0x30, 0x7F, 0x30, 0x2F, 0x9A, 0x71, 0x73, 0x44, 0x73, 0xF5, 0x38, 0x01, 0xA0, 0x7F, 0xC1, 0x20, 0x7F, 0x3E, 0x8E, 0x02, 0xD0, 0x7F, 0x52, 0x65, 0x64, 0x01, 0x70, 0xFF, 0xC1, 0xEB, 0x45, 0x43, 0xC2, 0x14, 0xB7, 0x6D, 0xDB, 0x20, 0x7F, 0x8C, 0x25, 0x02, 0x20, 0xC1, 0xD4, 0x00, 0xD1, 0x8B, 0xB6, 0x6C, 0x5C, 0xA4, 0x87, 0xB4, 0x41, 0x3B, 0x92, 0x24, 0x2F, 0xE9, 0xC0, 0x60, 0x8B, 0x31, 0x00, 0x32, 0xE7, 0x35, 0x33, 0xF2, 0xE7, 0x92, 0x53, 0x5F, 0xF0, 0x26, 0x82, 0x20, 0x25, 0x1B, 0x90, 0x0B, 0x50, 0x97, 0x34, 0xEF, 0x00, 0x50, 0x97, 0xEB, 0x96, 0x53, 0x30, 0x3B, 0x77, 0x08, 0xAA, 0xF1, 0x17, 0x32, 0x02, 0x13, 0x73, 0x32, 0xF7, 0xFE, 0x50, 0x8B, 0x00, 0x96, 0x7B, 0x33, 0x1B, 0x57, 0x7C, 0x00, 0x31, 0x7F, 0x3B, 0xB0, 0x57, 0x07, 0x54, 0x6D, 0x53, 0x2B, 0x0E, 0x47, 0x73, 0x4C, 0x37, 0x8B, 0x2B, 0xF9, 0x94, 0x63, 0x8B, 0xD8, 0x3B, 0xA7, 0x3B, 0xF1, 0x24, 0x4B, 0xF5, 0x00, 0x01, 0x97, 0xC0, 0x39, 0x8E, 0x7A, 0xE3, 0x2B, 0x59, 0x51, 0x5B, 0x5C, 0x1D, 0x01, 0x20, 0x23, 0x03, 0xF7, 0x6B, 0x40, 0x04, 0x41, 0x9E, 0x15, 0x8D, 0xBD, 0x31, 0xA3, 0x9A, 0x99, 0x6A, 0xB9, 0x2B, 0x9D, 0x2C, 0x7A, 0x04, 0x01, 0x10, 0x23, 0x01, 0x01, 0x20, 0x8F, 0x01, 0xAB, 0x01, 0x20, 0x8F, 0x01, 0x00, 0x10, 0x8F, 0xC1, 0x20, 0x8F, 0x3D, 0x60, 0x8F, 0x44, 0x5B, 0x60, 0x01, 0x00, 0x10, 0x8F, 0x00, 0x00, 0x23, 0x50, 0x5F, 0x42, 0x6C, 0x6B, 0x80, 0x03, 0xE1, 0x63, 0x9A, 0x99, 0x19, 0xC0, 0x0E, 0x74, 0xDA, 0xFF, 0x00, 0xC1, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0x03, 0x81, 0x63, 0x00, 0x13, 0xBB, 0xAA, 0x00, 0x32, 0xC7, 0x58, 0x2E, 0xBD, 0x88, 0x66, 0x4F, 0xE8, 0x2E, 0xC9, 0x18, 0xAF, 0x2E, 0xB5, 0x48, 0x2E, 0xB9, 0x78, 0x62, 0xC7, 0xE3, 0xD3, 0x56, 0x3F, 0x60, 0x0B, 0xBD, 0x52, 0xD3, 0xF0, 0xC2, 0xD3, 0x01, 0xC0, 0x2F, 0x22, 0xDF, 0xD4, 0x33, 0x40, 0x68, 0x03, 0xDF, 0x50, 0x0B, 0x52, 0xEB, 0xF0, 0xC2, 0xEB, 0x01, 0xB0, 0x2F, 0x32, 0xF7, 0x01, 0xB0, 0xBF, 0x33, 0x03, 0xFF, 0x01, 0xC0, 0x2F, 0x00, 0x10, 0xBF, 0x45, 0x73, 0x70, 0x0B, 0x53, 0x1B, 0x40, 0xBF, 0x83, 0x1B, 0x01, 0xB0, 0x2F, 0xFF, 0x63, 0x27, 0x03, 0xC1, 0xC3, 0x33, 0x27, 0x75, 0x97, 0x93, 0x33, 0x00, 0x91, 0xC3, 0x01, 0x00, 0x2F, 0x05, 0xE1, 0xC3, 0xFF, 0x00, 0xF0, 0xBF, 0xF1, 0xC3, 0x01, 0x00, 0x2F, 0x05, 0x01, 0xC3, 0x00, 0x16, 0xB7, 0x00, 0x36, 0x4F, 0x35, 0xCC, 0x33, 0x8B, 0xD7, 0x36, 0x53, 0x33, 0x8F, 0xA0, 0x69, 0xE3, 0xD0, 0x6D, 0xAB, 0xE6, 0xCF, 0x59, 0xC7, 0xFF, 0x26, 0x43, 0x00, 0x40, 0x17, 0x26, 0x37, 0xD6, 0xFF, 0x63, 0x57, 0x26, 0x2B, 0x00, 0x30, 0x17, 0x36, 0x1F, 0xFF, 0x00, 0x30, 0x5F, 0x36, 0x13, 0x00, 0x40, 0x17, 0x00, 0x10, 0x5F, 0x48, 0x6B, 0x35, 0xFB, 0x00, 0x30, 0x17, 0x65, 0xEF, 0xFF, 0x03, 0xC1, 0x03, 0x82, 0xC7, 0xE1, 0x03, 0x82, 0xDF, 0x02, 0xE1, 0x03, 0x73, 0x27, 0xF1, 0x03, 0x80, 0x17, 0xDB, 0x01, 0xE1, 0x03, 0x00, 0xFD, 0xDF, 0x54, 0xEC, 0xDF, 0x02, 0x7E, 0xDF, 0x04, 0x2F, 0xA4, 0x5F, 0x0D, 0xAA, 0xDC, 0xDF, 0x50, 0x2F, 0xCC, 0xB8, 0x2F, 0xD0, 0x20, 0x2F, 0xBC, 0xA0, 0xAA, 0x2F, 0xC0, 0x2C, 0x2C, 0xE3, 0xAC, 0x2C, 0xE7, 0x10, 0x2C, 0xDF, 0x74, 0x97, 0x2C, 0xDF, 0xD8, 0x07, 0x2D, 0x17, 0x09, 0x2C, 0x31, 0x2C, 0xE3, 0x02, 0x9C, 0xDF, 0xF5, 0x3E, 0xCF, 0x00, 0xFC, 0xDF, 0x9E, 0xF3, 0x00, 0xBC, 0xDF, 0x7C, 0xEC, 0xDF, 0x2C, 0x6D, 0x5B, 0xFF, 0xDD, 0x4F, 0x4C, 0xE3, 0x8C, 0xD3, 0xD0, 0x17, 0x9C, 0xBB, 0x00, 0x30, 0x17, 0x00, 0x9F, 0xD3, 0x3F, 0xFD, 0xEF, 0x01, 0x1C, 0x8B, 0x00, 0x0D, 0xE7, 0xC3, 0xA3, 0xA0, 0x81, 0xF3, 0x00, 0x9F, 0xFB, 0x30, 0x23, 0x01, 0x1C, 0x73, 0xDB, 0x03, 0xD0, 0x67, 0x02, 0x7C, 0x5B, 0x70, 0x2B, 0xCB, 0x7C, 0x5B, 0x20, 0x3B, 0xDB, 0x00, 0xEB, 0xC3, 0xFB, 0x3E, 0x67, 0x7F, 0xD7, 0x5B, 0xCF, 0x00, 0xFC, 0x4F, 0x00, 0xDC, 0xDB, 0xF0, 0x2C, 0xCB, 0x80, 0x7F, 0xEF, 0x01, 0x2C, 0xDB, 0x30, 0x2F, 0x7F, 0xFB, 0xC8, 0x2F, 0x03, 0x7C, 0xDB, 0x5B, 0xE7, 0xAC, 0xDB, 0xFF, 0x00, 0x4C, 0x4F, 0x03, 0x3D, 0x67, 0x00, 0x1E, 0x67, 0xDD, 0x67, 0x04, 0x1C, 0x67, 0x41, 0xA3, 0x79, 0x93, 0x9D, 0x43, 0xFF, 0xCC, 0x67, 0x00, 0x60, 0x23, 0xCC, 0x67, 0x31, 0xEB, 0x89, 0x7B, 0x28, 0x2F, 0x00, 0x3C, 0x67, 0x00, 0x50, 0x23, 0xFF, 0xDC, 0x67, 0x00, 0x50, 0x8F, 0xDC, 0x67, 0x00, 0x60, 0x23, 0x00, 0x10, 0x8F, 0x79, 0x4B, 0x30, 0x8F, 0x00, 0x2C, 0x67, 0xCF, 0x00, 0x50, 0x23, 0x04, 0x1C, 0x67, 0x70, 0xC2, 0xA9, 0x33, 0x00, 0x81, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0xFF, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0x03, 0x81, 0x63, 0x01, 0x5C, 0x67, 0x01, 0x9F, 0x2F, 0x43, 0xEB, 0x6F, 0x2F, 0xFF, 0x9F, 0x97, 0xDF, 0x2F, 0x00, 0x60, 0x23, 0xCF, 0x2F, 0x34, 0x33, 0x7F, 0x2F, 0x38, 0x2F, 0x00, 0x3F, 0x2F, 0xFF, 0x00, 0x50, 0x23, 0xDF, 0x2F, 0x00, 0x50, 0x8F, 0xDF, 0x2F, 0x00, 0x60, 0x23, 0x00, 0x10, 0x8F, 0x6F, 0x2F, 0x40, 0x8F, 0xFF, 0x00, 0x2F, 0x2F, 0x00, 0x50, 0x23, 0x01, 0x7C, 0x07, 0x01, 0xB1, 0x63, 0x9F, 0x2F, 0x00, 0x91, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0xFF, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0x03, 0x81, 0x63, 0x01, 0x5B, 0xA7, 0x01, 0x95, 0x8F, 0x46, 0x27, 0x6F, 0x23, 0xFF, 0x9F, 0xDF, 0xD5, 0x8F, 0x00, 0x60, 0x23, 0xC5, 0x8F, 0x4F, 0xDF, 0x6F, 0x0B, 0x4F, 0xDF, 0x00, 0x25, 0x8F, 0xFF, 0x00, 0x50, 0x23, 0xD5, 0x8F, 0x00, 0x50, 0x8F, 0xD5, 0x8F, 0x00, 0x60, 0x23, 0x00, 0x10, 0x8F, 0x6E, 0xDB, 0x40, 0x8F, 0xFF, 0x00, 0x25, 0x8F, 0x00, 0x50, 0x23, 0x01, 0x7C, 0x07, 0x01, 0xB1, 0x63, 0x9E, 0xC3, 0x00, 0x91, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0xFB, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0x03, 0x61, 0x63, 0x00, 0x7C, 0x5F, 0x4C, 0x2C, 0x5C, 0xBC, 0x5F, 0xC6, 0x3E, 0x51, 0x7C, 0x5F, 0x65, 0x00, 0x73, 0xCC, 0x5F, 0x3B, 0x9C, 0x47, 0x2B, 0x5F, 0x43, 0x00, 0x4C, 0x5F, 0xFC, 0x2E, 0xBB, 0x0F, 0x5B, 0x58, 0x4C, 0x5F, 0xD5, 0x3C, 0x82, 0x3B, 0xAB, 0xBC, 0x2F, 0xFF, 0xFC, 0x2F, 0xF8, 0x3C, 0x2E, 0xDB, 0x5F, 0x7C, 0x2E, 0xDF, 0xBC, 0x2E, 0xE3, 0x00, 0x3C, 0x47, 0x3E, 0xC7, 0x5E, 0xFB, 0x00, 0x7A, 0x3B, 0x2F, 0x80, 0xBF, 0x9A, 0x3B, 0x60, 0x88, 0xC7, 0x00, 0x3C, 0x2B, 0x00, 0x70, 0x4B, 0x9F, 0x2B, 0x77, 0xCA, 0x2A, 0xB7, 0x00, 0x9B, 0xCB, 0x01, 0x10, 0x3F, 0xF2, 0xA0, 0x3F, 0x00, 0x1B, 0xA3, 0x01, 0xD0, 0x3F, 0xDE, 0x00, 0x29, 0xEF, 0x01, 0x00, 0xBF, 0x8E, 0x2B, 0x77, 0x70, 0xFF, 0x00, 0x27, 0x67, 0x01, 0x00, 0xFF, 0x24, 0xEC, 0xF0, 0x3F, 0xDF, 0x83, 0x01, 0x01, 0x3F, 0x30, 0x00, 0x8E, 0xBB, 0x5E, 0xBF, 0x59, 0x54, 0xA8, 0x7E, 0xBF, 0xB4, 0x2E, 0xBC, 0x10, 0x2F, 0xFB, 0x6C, 0x79, 0x74, 0x64, 0x31, 0x3E, 0xD1, 0x4A, 0x9E, 0x00, 0xA0, 0x2D, 0xE7, 0x70, 0x43, 0x05, 0x74, 0x78, 0x6C, 0x31, 0x34, 0x61, 0xFB, 0x04, 0x2F, 0xFF, 0x80, 0x2D, 0x55, 0x74, 0x65, 0x6E, 0x64, 0x6F, 0x5F, 0x44, 0x00, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x00, 0x65, 0x64, 0x42, 0x79, 0x5F, 0x31, 0x32, 0x38, 0x00, 0x78, 0x36, 0x34, 0x2E, 0x62, 0x63, 0x6C, 0x69, 0x17, 0x6D, 0x00, 0x6D, 0x2F, 0x07, 0x60, 0x62, 0x2F, 0x30, 0x57, 0x4D, 0x8B, 0x08, 0x4C, 0x6F, 0x67, 0x6F, 0xAE, 0xF5, 0xFF, 0xFF, 0xFF, 0xDF, 0x30, 0x03, 0x00, 0x40, 0x02, 0x15, 0x5F, 0xEC, 0x30, 0x6E, 0xAF, 0x7E, 0x3E, 0x13, 0x5E, 0x17, 0x08, 0x70, 0x61, 0x6E, 0x31, 0x3B, 0x5B, 0x01, 0x04, 0xFF, 0x00, 0x00, 0x52, 0x6F, 0x6F, 0x74, 0x50, 0x61, 0x6E, 0x70, 0x65, 0x00, 0xB0, 0xEB, 0x00, 0x50, 0x47, 0x50, 0xDF, 0x70, 0x61, 0x73, 0x31, 0xD3, 0x3B, 0xAF, 0x70, 0x53, 0x03, 0x20, 0x53, 0x4E, 0x5F, 0x30, 0x55, 0x00, 0x0F, 0xA2, 0xD0, 0x01, 0x20, 0x53, 0x4C, 0xDF, 0x42, 0x80, 0x53, 0x69, 0x63, 0x31, 0x80, 0x9F, 0x3C, 0x1B, 0x07, 0xFF, 0x00, 0x41, 0x03, 0x7E, 0xEC, 0x2D, 0x67, 0x82, 0x2B, 0x00, 0x20, 0xEF, 0x9E, 0x2F, 0x6F, 0x80, 0x42, 0xF1, 0x2B, 0x71, 0xA5, 0xCF, 0x2F, 0xC1, 0x27, 0x80, 0x0C, 0x3F, 0x70, 0x61, 0x65, 0x60, 0xDB, 0x50, 0x07, 0x67, 0x72, 0x30, 0x70, 0x31, 0x3C, 0xA3, 0x31, 0x33, 0x47, 0x72, 0x6F, 0x75, 0xCE, 0x3C, 0x9B, 0x7F, 0xF3, 0x67, 0x72, 0x51, 0x07, 0x30, 0x23, 0x34, 0x63, 0x47, 0x3F, 0x5F, 0x41, 0xCF, 0xDF, 0x3F, 0xDB, 0xF1, 0x17, 0xF1, 0xD7, 0x30, 0x5F, 0x3F, 0xEB, 0x1F, 0x47, 0x5F, 0x42, 0xCF, 0x79, 0x3F, 0xF3, 0x00, 0x90, 0x2B, 0xD4, 0xAB, 0x3F, 0xEF, 0x9A, 0xF1, 0x7F, 0x67, 0x72, 0x50, 0xC7, 0x00, 0x72, 0xBF, 0x3C, 0x22, 0xBC, 0x22, 0xB5, 0x00, 0x02, 0xBF, 0xC8, 0x82, 0xBF, 0x3D, 0x7F, 0x07, 0x64, 0xBB, 0x2D, 0x2F, 0xFF, 0x9D, 0x2F, 0x08, 0x00, 0x4F, 0x34, 0xA1, 0x32, 0xF3, 0x2F, 0xFF, 0x78, 0x2F, 0xFB, 0x1D, 0x33, 0x64, 0x73, 0x62, 0xA1, 0x62, 0xC4, 0x80, 0x10, 0x31, 0xF0, 0x10, 0x53, 0x32, 0xF0, 0x21, 0x33, 0x62, 0xF7, 0x4C, 0x54, 0x90, 0x3E, 0x30, 0x0B, 0x83, 0x70, 0x39, 0x4C, 0x54, 0x4D, 0x61, 0x73, 0x3C, 0xCC, 0xA3, 0x1F, 0x05, 0xA8, 0x06, 0x00, 0x00, 0x0B, 0x2F, 0xFF, 0x38, 0x2F, 0xFF, 0x55, 0x88, 0x2F, 0xFB, 0x08, 0x2F, 0xF4, 0x88, 0x2F, 0xF8, 0x08, 0x2F, 0xD4, 0x55, 0x88, 0x2F, 0xD8, 0x4C, 0x2F, 0x10, 0xE8, 0x2F, 0x14, 0xAC, 0x23, 0x74, 0x3B, 0x48, 0x05, 0x2F, 0xD7, 0x20, 0x2F, 0x00, 0x35, 0x47, 0xAA, 0x53, 0x4B, 0x00, 0x83, 0x47, 0x76, 0x02, 0x00, 0xA3, 0x47, 0x00, 0x35, 0x57, 0x00, 0xB3, 0x97, 0xD5, 0x20, 0xB3, 0x00, 0xB3, 0x97, 0x40, 0xD0, 0x24, 0x20, 0x30, 0x03, 0x11, 0x2F, 0xFB, 0x74, 0x06, 0x00, 0x04, 0xC3, 0x30, 0x03, 0x30, 0x0B, 0x65, 0x06, 0x00, 0x01, 0x30, 0x03, 0x30, 0x17, 0xD3, 0x31, 0x87, 0x5E, 0x03, 0x05, 0x2F, 0x47, 0x4F, 0x5F, 0x31, 0x32, 0x01, 0xB0, 0x7F, 0x60, 0x01, 0x03, 0xE0, 0x7F, 0xD2, 0xA9, 0x00, 0x00, 0x8C, 0x8C, 0x8C, 0xEF, 0x05, 0xA0, 0x7F, 0x00, 0x16, 0x97, 0x00, 0xF1, 0x7F, 0x03, 0x03, 0xC1, 0x7F, 0x00, 0x16, 0xD7, 0x45, 0x9B, 0x2F, 0xB4, 0x96, 0x00, 0x25, 0x9B, 0x80, 0x3F, 0x23, 0x44, 0x04, 0x25, 0x97, 0x30, 0x03, 0x06, 0x01, 0x00, 0x06, 0x06, 0x73, 0x09, 0xED, 0xBE, 0x30, 0x03, 0x86, 0x3F, 0xFB, 0x3A, 0x57, 0xDE, 0x40, 0x30, 0x03, 0xE0, 0x13, 0xC0, 0xE0, 0x30, 0x03, 0x00, 0x75, 0xC7, 0x78, 0x54, 0x10, 0x04, 0x00, 0x01, 0x10, 0x14, 0x04, 0x10, 0x02, 0xA2, 0x37, 0x46, 0xF2, 0x37, 0x26, 0x06, 0x1F, 0x02, 0x05, 0x66, 0x23, 0x33, 0x00, 0x12, 0x43, 0x4D, 0x5F, 0x00, 0x35, 0xAA, 0x00, 0x36, 0x5E, 0x2C, 0x80, 0xEA, 0x23, 0x77, 0x05, 0x26, 0x5B, 0x30, 0x03, 0x30, 0x8E, 0x3E, 0xE3, 0xBE, 0x30, 0x03, 0xB0, 0xBF, 0xE0, 0x13, 0xC0, 0xBF, 0x50, 0xA7, 0x00, 0xF0, 0x00, 0xC0, 0xA7, 0x00, 0x21, 0x5F, 0xCF, 0x5F, 0x01, 0xB1, 0x5F, 0x2F, 0xA1, 0xBD, 0xBF, 0xC3, 0x30, 0x03, 0x3F, 0xF7, 0xCE, 0x95, 0x17, 0x41, 0x30, 0x03, 0xE0, 0x13, 0x78, 0xC1, 0x30, 0x03, 0x05, 0x21, 0x5F, 0x00, 0x00, 0xC3, 0x01, 0x31, 0x5F, 0x61, 0x0B, 0xB6, 0x7F, 0xBF, 0x30, 0x03, 0xB0, 0xBF, 0xE0, 0x13, 0xC0, 0xBF, 0x02, 0x61, 0x5F, 0xCD, 0xF7, 0x01, 0xB2, 0xBF, 0xFF, 0x3F, 0xF7, 0x50, 0x03, 0x5D, 0xA7, 0x50, 0x03, 0xC0, 0x13, 0x4F, 0xF7, 0x05, 0x22, 0xBF, 0x00, 0x00, 0xC3, 0xFF, 0x01, 0x32, 0xBF, 0x3F, 0xE3, 0x3F, 0xE7, 0xB0, 0xBF, 0xE0, 0x13, 0xC0, 0xBF, 0x01, 0xF2, 0xBF, 0x03, 0x59, 0x67, 0xFF, 0x57, 0x87, 0x00, 0x59, 0x67, 0x00, 0x1C, 0x63, 0x99, 0x13, 0x40, 0x03, 0x00, 0x79, 0x13, 0x3F, 0x93, 0xC9, 0x67, 0x58, 0xA0, 0x4E, 0xC7, 0xF5, 0x00, 0x84, 0xD3, 0x70, 0x53, 0x46, 0x31, 0x32, 0xE8, 0x00, 0x63, 0x2F, 0x58, 0x2F, 0xFA, 0x93, 0x05, 0x4F, 0xF1, 0x00, 0x00, 0xCD, 0x27, 0xCC, 0x4C, 0x28, 0x36, 0x80, 0x3F, 0x50, 0x07, 0x40, 0x0F, 0x4A, 0x8F, 0xFF, 0x50, 0x07, 0x9F, 0xEC, 0xE0, 0x0B, 0x40, 0x03, 0x00, 0x0A, 0x0F, 0x2A, 0xB7, 0x00, 0xA4, 0xB7, 0x60, 0xFB, 0x7D, 0x20, 0x01, 0xC0, 0xA7, 0x27, 0x62, 0x01, 0x00, 0xA7, 0x8A, 0x0F, 0x81, 0x2F, 0x91, 0x00, 0x84, 0xA3, 0x8B, 0x71, 0x83, 0x10, 0xF4, 0xBF, 0x01, 0xC1, 0x2F, 0x07, 0x04, 0xD1, 0x2F, 0x00, 0x80, 0xA7, 0xBE, 0x01, 0xF1, 0x2F, 0x08, 0x02, 0x41, 0x2F, 0x00, 0x5D, 0x8B, 0xE1, 0xB7, 0xEB, 0xCB, 0x00, 0xD2, 0x5F, 0x09, 0xEF, 0x04, 0xD2, 0x5F, 0x00, 0xB0, 0xA7, 0x01, 0xC3, 0x07, 0x0A, 0x01, 0xE2, 0x5F, 0x92, 0xE7, 0x00, 0x1F, 0xFB, 0x5F, 0xC7, 0x6B, 0xF8, 0x25, 0x6F, 0x3C, 0xFB, 0xA0, 0x00, 0x68, 0x1F, 0x10, 0x43, 0xE3, 0x00, 0x5C, 0xF7, 0x47, 0x50, 0x43, 0x83, 0x00, 0x00, 0x44, 0x6C, 0xF7, 0x30, 0x0F, 0x3E, 0x1F, 0xE7, 0x30, 0x0F, 0x2C, 0xF7, 0x6D, 0x77, 0x03, 0x08, 0x6D, 0x77, 0x00, 0xC3, 0x67, 0x00, 0x70, 0x7F, 0xAF, 0x4D, 0x77, 0x41, 0xFE, 0xA3, 0x01, 0x01, 0x4D, 0x77, 0x00, 0x3D, 0xFF, 0x00, 0x1A, 0xEB, 0x01, 0x94, 0xEB, 0xF7, 0x00, 0x10, 0x87, 0x5F, 0xE9, 0x00, 0xED, 0xFF, 0x7E, 0x7F, 0x01, 0x50, 0x7F, 0xFA, 0xEB, 0x02, 0xB0, 0x7F, 0x7B, 0x03, 0x8E, 0x7F, 0x9E, 0x6F, 0xFE, 0x8F, 0x00, 0x02, 0x0F, 0x03, 0x3F, 0x07, 0x00, 0x1A, 0xF3, 0xF5, 0x01, 0x91, 0x8F, 0x00, 0x12, 0x0F, 0x2A, 0x3A, 0x04, 0x8F, 0x07, 0xDC, 0x00, 0x2F, 0x07, 0x0C, 0x4F, 0x07, 0xFF, 0xD6, 0xB7, 0xFD, 0x97, 0xFD, 0x57, 0xFC, 0xE7, 0xFC, 0x77, 0xFC, 0x07, 0xFB, 0x97, 0xFA, 0xE3, 0xFB, 0xFA, 0x57, 0xF9, 0xA3, 0xF9, 0x17, 0xF8, 0x63, 0x3F, 0xE3, 0xCC, 0x00, 0x2F, 0xA7, 0x3E, 0x8F, 0xAE, 0x0A, 0x30, 0xCB, 0x2C, 0x41, 0xA7, 0x43, 0xCF, 0x1B, 0x37, 0x0D, 0xF8, 0x5F, 0x67, 0x60, 0x72, 0x56, 0xFF, 0x01, 0x48, 0xC3, 0x40, 0x00, 0x78, 0x80, 0x80, 0x8C, 0x34, 0x6F, 0x00, 0x00, 0x0A, 0x2B, 0x81, 0x20, 0x0B, 0xEF, 0x80, 0x00, 0x80, 0xEF, 0xEF, 0xFF, 0xF8, 0x0B, 0xBF, 0x70, 0x10, 0x01, 0xFF, 0xF6, 0x8F, 0x85, 0x20, 0x00, 0x88, 0x40, 0x41, 0x30, 0x50, 0x27, 0x1C, 0xCF, 0x00, 0x01, 0x30, 0x20, 0x0B, 0xE0, 0x30, 0x03, 0x38, 0x36, 0x4F, 0x79, 0x87, 0x00, 0x05, 0xFD, 0xFC, 0x30, 0x0B, 0x0A, 0x3F, 0x85, 0x3F, 0x89, 0xFC, 0xFC, 0x0A, 0x0A, 0xC1, 0x30, 0x03, 0x2F, 0xFA, 0x83, 0x00, 0x00, 0xF7, 0xF7, 0x3F, 0x10, 0x38, 0xBF, 0xFF, 0x31, 0x7A, 0x20, 0x0B, 0x20, 0x0F, 0xFF, 0x9F, 0xCF, 0x04, 0xFF, 0x1F, 0x2F, 0xF6, 0x60, 0xAF, 0xE5, 0x81, 0x00, 0x09, 0x00, 0xF3, 0xF3, 0x01, 0x22, 0xB0, 0xCF, 0xFF, 0x30, 0x05, 0x20, 0xF3, 0xF3, 0x40, 0x03, 0x28, 0x00, 0x00, 0x5F, 0x5F, 0x83, 0x40, 0x5F, 0x88, 0xFE, 0xCA, 0xFF, 0xCC, 0x30, 0x0B, 0x40, 0x0F, 0x83, 0x7F, 0xEC, 0x88, 0x00, 0x88, 0xFF, 0xCC, 0x2F, 0xCC, 0x30, 0x07, 0x25, 0xCF, 0xFF, 0x21, 0xEE, 0xFC, 0xFC, 0x30, 0x7D, 0x0C, 0x22, 0xC0, 0xC0, 0x30, 0x03, 0x20, 0x1F, 0x06, 0xFF, 0xCC, 0x0D, 0x0A, 0x00, 0x07, 0x30, 0x00, 0x88, 0x60, 0x60, 0x50, 0xE7, 0x3F, 0xFF, 0x30, 0x0B, 0xD9, 0x40, 0x0F, 0x30, 0x3F, 0xCD, 0x20, 0x37, 0x50, 0x47, 0xCC, 0x02, 0x2D, 0xA7, 0x16, 0x34, 0xFF, 0x33, 0x41, 0x0F, 0x33, 0x30, 0x07, 0x40, 0x3F, 0x0E, 0xAF, 0x30, 0xC7, 0x84, 0x25, 0xCB, 0xF8, 0x4F, 0xD3, 0x2F, 0x9F, 0x50, 0x0B, 0x20, 0x0F, 0x8C, 0x2F, 0xE8, 0xAF, 0xFF, 0x00, 0x30, 0xE7, 0x5F, 0xD7, 0x8E, 0xBF, 0x05, 0xFF, 0x0E, 0x1E, 0xF7, 0x70, 0x32, 0x64, 0xBF, 0x40, 0xC7, 0x04, 0x00, 0x82, 0x00, 0x00, 0xF4, 0x40, 0xC7, 0x4F, 0x4F, 0xF0, 0x3F, 0xFF, 0x50, 0xD7, 0x30, 0x0B, 0x40, 0x0F, 0x80, 0x00, 0x88, 0xF1, 0x10, 0xE1, 0xFF, 0xEF, 0x70, 0x7F, 0xE1, 0xE1, 0x7F, 0x7F, 0xC0, 0x30, 0x03, 0xE0, 0xDF, 0xDC, 0x00, 0x15, 0x00, 0x00, 0xEF, 0x31, 0xFF, 0x05, 0x40, 0x41, 0x3F, 0xDA, 0xD3, 0x40, 0xDF, 0x2E, 0xBE, 0x33, 0xFD, 0xFA, 0x00, 0x0E, 0x0F, 0x2F, 0xB5, 0x07, 0x09, 0x01, 0xAA, 0xBD, 0x21, 0xEB, 0x8C, 0x31, 0xEF, 0x01, 0x01, 0x60, 0x25, 0x3F, 0x40, 0x0F, 0xFF, 0x70, 0x18, 0x00, 0xDE, 0x01, 0x30, 0x0B, 0x39, 0x69, 0xFF, 0xF6, 0x1C, 0x00, 0xCF, 0x50, 0x00, 0xFF, 0xF5, 0x30, 0x31, 0xFF, 0x28, 0xFF, 0x5C, 0x46, 0x97, 0x50, 0x5F, 0xBF, 0xF5, 0xFF, 0xFF, 0x0E, 0x40, 0x00, 0xEE, 0x10, 0xF1, 0xEF, 0x41, 0xFF, 0x2F, 0xFF, 0xFC, 0x06, 0xFD, 0x0A, 0x0B, 0xEB, 0x10, 0x30, 0x88, 0x51, 0xEF, 0x2F, 0x19, 0x2F, 0x00, 0x00, 0x30, 0x03, 0x51, 0xFF, 0xE6, 0x10, 0x30, 0x0F, 0x48, 0x2E, 0x2F, 0xE0, 0xF5, 0x50, 0x30, 0xC7, 0xF5, 0x40, 0x02, 0x0D, 0x1D, 0xF3, 0xF2, 0xDF, 0x20, 0x54, 0x7F, 0xF3, 0xF4, 0x2F, 0x99, 0x1D, 0x00, 0x00, 0xD4, 0x41, 0xFB, 0xB1, 0xEF, 0x32, 0x0B, 0x4E, 0xB6, 0x9A, 0xC3, 0xF1, 0xEF, 0x20, 0x79, 0x00, 0x00, 0xEB, 0x10, 0x31, 0xFF, 0x33, 0xE7, 0xC0, 0x00, 0x01, 0xEF, 0xB1, 0xFF, 0x00, 0xEE, 0x11, 0xFF, 0x35, 0xFF, 0x68, 0x33, 0x30, 0xF7, 0x21, 0xF2, 0x33, 0x3F, 0xDF, 0x57, 0xFF, 0x55, 0x02, 0xFF, 0xEE, 0x11, 0xEE, 0x11, 0x55, 0x60, 0x07, 0x06, 0xC0, 0x87, 0x06, 0x51, 0xEF, 0x55, 0xFF, 0x04, 0x0D, 0xEE, 0x11, 0xC0, 0x34, 0x41, 0x32, 0x0B, 0xE7, 0x10, 0x1E, 0x1E, 0x00, 0x00, 0x88, 0x30, 0x03, 0xF6, 0x60, 0xCF, 0x2E, 0xEE, 0xF6, 0x50, 0x1E, 0x08, 0x1F, 0x00, 0x00, 0x1D, 0xAF, 0xA4, 0x01, 0x1C, 0xF3, 0x32, 0xF3, 0xCF, 0x21, 0x2C, 0x71, 0xEF, 0xF5, 0x50, 0x37, 0xDB, 0xE4, 0xE8, 0x42, 0x0B, 0x30, 0xC7, 0x61, 0xEF, 0x6F, 0x7F, 0xD7, 0xE1, 0xF1, 0xAF, 0x38, 0xFF, 0xD1, 0x20, 0x97, 0x70, 0x7F, 0x9F, 0xEF, 0xF9, 0xFB, 0x10, 0x28, 0x90, 0xFE, 0x20, 0x9D, 0x65, 0x30, 0x9F, 0x01, 0xFB, 0xFF, 0x1B, 0x9F, 0x0B, 0x7C, 0x33, 0xB3, 0x2C, 0x6C, 0x06, 0x5B, 0xBA, 0x00, 0x4C, 0xB2, 0x01, 0x43, 0x4C, 0x49, 0x4D, 0xFF, 0xFE, 0x14, 0x2F, 0xFA, 0x18, 0x02, 0x02, 0x28, 0x29, 0xD7, 0x3B, 0x3D, 0x69, 0x6D, 0x61, 0x23, 0x67, 0x10, 0x4C, 0x7C, 0x10, 0x00, 0x0D, 0x62, 0x33, 0x06, 0xD0, 0x01, 0x0A, 0x20, 0xA0, 0x00, 0x71, 0x23, 0xDF, 0xFF, 0x33, 0xBF, 0xC0, 0x80, 0x2E, 0xAB, 0xC0, 0xC0, 0xAF, 0x9F, 0x00, 0x00, 0x9F, 0xF0, 0x20, 0x03, 0x73, 0x97, 0x80, 0x07, 0xFF, 0xA0, 0x78, 0x00, 0x02, 0xFF, 0x30, 0xFC, 0x3E, 0x4F, 0x7B, 0x3F, 0xCE, 0x90, 0x90, 0xDF, 0xDF, 0xF9, 0x30, 0x03, 0x01, 0x9D, 0xBF, 0x50, 0x6F, 0x30, 0x6B, 0x40, 0x6F, 0x00, 0xB0, 0x44, 0x93, 0x47, 0xDF, 0x22, 0x07, 0xD7, 0x00, 0xEE, 0x00, 0x0E, 0xAE, 0x42, 0x17, 0x20, 0x17, 0xD0, 0x70, 0x07, 0x40, 0x6F, 0x80, 0x90, 0x6F, 0xC5, 0xFF, 0xCF, 0x7F, 0x3D, 0xDE, 0x00, 0x95, 0x7D, 0xC1, 0x7F, 0x63, 0x53, 0x71, 0x7F, 0x20, 0x71, 0x7F, 0xD6, 0xC2, 0xCF, 0x06, 0xB1, 0x8B, 0x50, 0xA8, 0x22, 0x70, 0x28, 0x2E, 0x2D, 0xE6, 0x10, 0x11, 0x00, 0x43, 0xFD, 0x3A, 0x8F, 0x76, 0x00, 0x98, 0x6F, 0xA8, 0x21, 0xCE, 0x47, 0x2D, 0x83, 0xFF, 0x7A, 0xFF, 0x45, 0x4F, 0xDE, 0x14, 0xAA, 0x00, 0xBB, 0x4A, 0xAF, 0xBB, 0x50, 0x07, 0xFF, 0x23, 0x42, 0xEF, 0x42, 0xB3, 0xFF, 0x21, 0xFF, 0x53, 0x4F, 0xFE, 0x9A, 0x28, 0x00, 0x68, 0x4A, 0xCF, 0x24, 0x3F, 0xE8, 0xAD, 0xFF, 0xFF, 0x54, 0xC8, 0x3A, 0xDB, 0xB3, 0x5F, 0xF4, 0xFA, 0x56, 0x77, 0x27, 0xFF, 0x3F, 0x00, 0x4B, 0x85, 0x3F, 0x7B, 0x87, 0x26, 0x8B, 0x2D, 0xED, 0xB3, 0xC2, 0x07, 0xC0, 0x0A, 0x0E, 0x21, 0xF6, 0x22, 0xFF, 0x26, 0xC5, 0x86, 0x4F, 0x7F, 0xDD, 0x22, 0x23, 0xFF, 0x32, 0x4F, 0x5A, 0x43, 0xFF, 0x97, 0x6B, 0xC7, 0x37, 0x3B, 0x01, 0x10, 0xE7, 0xF2, 0xF4, 0xFF, 0xFF, 0xFC, 0x2F, 0x74, 0xD0, 0x30, 0x03, 0x9F, 0x7B, 0xDF, 0xAF, 0x86, 0x0C, 0x09, 0xFF, 0x4F, 0x00, 0x02, 0x00, 0xFF, 0xAD, 0xBF, 0x04, 0x28, 0xFF, 0x11, 0x00, 0x6C, 0x03, 0x07, 0xE0, 0xF8, 0xD6, 0x00, 0xDD, 0x00, 0x48, 0x51, 0x68, 0xDD, 0x26, 0x03, 0x61, 0xEF, 0x54, 0x00, 0x3C, 0xFD, 0xFF, 0xB8, 0xFF, 0x09, 0xFE, 0x00, 0x00, 0x51, 0x41, 0xEF, 0xFD, 0xA0, 0x97, 0x7F, 0x03, 0x10, 0x00, 0xFE, 0xFC, 0x10, 0xA0, 0x23, 0xF1, 0x6F, 0xE0, 0x00, 0x2C, 0xEF, 0x00, 0x03, 0xFF, 0xFF, 0x1E, 0x8F, 0xA8, 0xA1, 0x1B, 0xEF, 0x21, 0x1F, 0xAF, 0x05, 0x94, 0x99, 0xA1, 0xF2, 0x00, 0x38, 0x00, 0xF2, 0x20, 0x03, 0x85, 0x89, 0x40, 0xD7, 0x37, 0xFF, 0x01, 0x44, 0xBE, 0x4D, 0x8F, 0x58, 0x00, 0x23, 0x4F, 0xFF, 0x64, 0xFF, 0x45, 0xA7, 0x47, 0xE7, 0xDC, 0xFF, 0xED, 0x79, 0x80, 0xDE, 0x28, 0x80, 0x91, 0x30, 0xD2, 0xCC, 0xFF, 0x50, 0xCF, 0x21, 0x00, 0x32, 0x42, 0xDF, 0x23, 0x33, 0x00, 0x26, 0x52, 0x73, 0x30, 0xFB, 0x3F, 0x93, 0x40, 0x04, 0xA6, 0x63, 0x3F, 0x12, 0x38, 0x27, 0x7A, 0xEF, 0x35, 0x94, 0x72, 0xEF, 0x8E, 0x05, 0xFF, 0xFF, 0x2F, 0x05, 0x4D, 0x2F, 0xAA, 0x6B, 0x03, 0xE4, 0x0C, 0xBA, 0x00, 0xB5, 0xFF, 0x40, 0x29, 0xD4, 0x07, 0x55, 0xFF, 0x08, 0xC0, 0x7F, 0x91, 0x4A, 0x8B, 0x99, 0x3F, 0x00, 0x99, 0x5F, 0x97, 0x5A, 0x97, 0x8F, 0xA7, 0x70, 0x17, 0x60, 0x1F, 0x8F, 0xC7, 0x0D, 0x56, 0xFF, 0x55, 0x01, 0x37, 0x97, 0x90, 0x1F, 0x78, 0x4F, 0xE3, 0xCD, 0x27, 0xC0, 0x4A, 0x27, 0x97, 0xFF, 0x2A, 0xA7, 0x27, 0x85, 0x35, 0x26, 0xBF, 0xC4, 0x24, 0x07, 0x3F, 0xE7, 0x8B, 0xFF, 0x03, 0x44, 0x10, 0xC6, 0x00, 0x34, 0xFF, 0xD4, 0x80, 0x5F, 0x3F, 0xFF, 0x17, 0x9F, 0xD5, 0xEF, 0xFF, 0x33, 0x07, 0xCF, 0x45, 0x6F, 0x2B, 0x77, 0x3E, 0xEF, 0x3B, 0x7D, 0xAF, 0xF1, 0x11, 0x30, 0x20, 0xFB, 0x5F, 0xEF, 0xF3, 0xF9, 0xF8, 0x90, 0x3F, 0x26, 0x31, 0xB7, 0x22, 0x97, 0x00, 0x75, 0x85, 0xBF, 0x2F, 0xEA, 0xAF, 0x04, 0x0D, 0xFF, 0x9E, 0xFF, 0x45, 0x4F, 0xE1, 0xA9, 0x00, 0x51, 0x9A, 0x45, 0xBF, 0x89, 0x55, 0xA7, 0xFF, 0x22, 0xFF, 0x3E, 0x7F, 0x05, 0x00, 0xFF, 0x75, 0xFF, 0xDA, 0x4F, 0xFF, 0x23, 0x35, 0xB7, 0x41, 0x5E, 0x8A, 0x8F, 0xFF, 0xFF, 0x7F, 0x8F, 0x52, 0x23, 0x0C, 0xF7, 0x0D, 0x92, 0x31, 0xE1, 0xEF, 0xE1, 0xFF, 0x7F, 0xA7, 0x02, 0x2D, 0x07, 0x30, 0x03, 0xF0, 0x0F, 0xC1, 0x01, 0x1D, 0x86, 0x45, 0x3E, 0x00, 0xFB, 0xB0, 0xFF, 0xFF, 0x25, 0x13, 0xCE, 0x4C, 0x5F, 0x5F, 0xE8, 0xF2, 0xD0, 0x28, 0x8B, 0x25, 0x31, 0x77, 0x11, 0x0D, 0xE0, 0xA5, 0x1B, 0x96, 0x44, 0x2D, 0x69, 0xFB, 0x01, 0x07, 0xF8, 0xF2, 0x82, 0x86, 0x45, 0x0E, 0x50, 0x00, 0x2F, 0x3F, 0x2C, 0x87, 0xE5, 0x04, 0xFF, 0xFF, 0x20, 0x00, 0xFA, 0x2D, 0xB1, 0x0D, 0x6F, 0x87, 0x76, 0x87, 0x18, 0xEF, 0x00, 0x38, 0x77, 0x77, 0xC2, 0x5F, 0xAE, 0x2B, 0x0F, 0x6B, 0xFF, 0x01, 0xAF, 0x47, 0xCF, 0x4C, 0x6F, 0x26, 0x89, 0x00, 0x3E, 0x47, 0x72, 0x3A, 0x0D, 0xB4, 0x2F, 0x04, 0xF1, 0xFF, 0x7F, 0xF1, 0xA0, 0xB0, 0x2C, 0x0D, 0xF4, 0x87, 0x79, 0x7C, 0x00, 0x60, 0xFB, 0xFF, 0x28, 0x32, 0x00, 0xB0, 0x01, 0x24, 0x07, 0x1E, 0x4F, 0x08, 0x2F, 0x2C, 0x6F, 0x2E, 0xDD, 0xBD, 0xFE, 0xDB, 0x59, 0x00, 0x56, 0xD8, 0x5E, 0x97, 0xA5, 0x37, 0x87, 0x61, 0x00, 0x17, 0x9F, 0x38, 0x93, 0x40, 0xD2, 0x96, 0x9E, 0x7D, 0xDF, 0xFE, 0x28, 0xAF, 0xD0, 0xE1, 0x39, 0xF1, 0x1A, 0xEC, 0x27, 0x87, 0x2F, 0xF7, 0x2F, 0xE3, 0x3F, 0x2B, 0x55, 0x98, 0xBE, 0x04, 0x07, 0x1A, 0xFF, 0xFF, 0x08, 0x4F, 0x09, 0x0E, 0x13, 0xFF, 0x20, 0x4A, 0xBF, 0x22, 0x23, 0x00, 0x22, 0xC3, 0xEF, 0xDE, 0xFF, 0xDD, 0x55, 0x42, 0x60, 0x17, 0xC0, 0x30, 0x1F, 0x49, 0x23, 0xFF, 0xED, 0xFF, 0x00, 0x31, 0x00, 0x64, 0x95, 0x7A, 0xDB, 0x60, 0x37, 0xEE, 0x12, 0x2F, 0x61, 0x50, 0xFD, 0x84, 0xDA, 0x11, 0xFF, 0xBD, 0xFF, 0x69, 0x45, 0xE7, 0x14, 0x6B, 0x86, 0x9B, 0x0F, 0x8E, 0x5E, 0x01, 0x9F, 0x6C, 0x52, 0x00, 0x1C, 0x2A, 0x35, 0xC4, 0x2E, 0xEF, 0x2F, 0x03, 0xAD, 0x00, 0x47, 0x5A, 0x6F, 0xFD, 0x74, 0x8F, 0x4F, 0x9F, 0xB9, 0xFF, 0xDC, 0x4F, 0xFF, 0x28, 0x6C, 0x2B, 0xB2, 0x4F, 0x57, 0x35, 0xBB, 0xFF, 0x2B, 0xAA, 0x2D, 0x64, 0x10, 0x60, 0xB7, 0x32, 0x35, 0xDC, 0x0A, 0x10, 0x00, 0xB4, 0xEC, 0x2F, 0xD7, 0xF9, 0x7B, 0x78, 0xEF, 0x88, 0x68, 0x9F, 0x8B, 0xFF, 0x25, 0xAB, 0x8F, 0x6D, 0xFF, 0x8F, 0x2F, 0x02, 0x00, 0x3F, 0xCD, 0x6C, 0x01, 0xEC, 0xAC, 0xCE, 0x7F, 0x2E, 0xAB, 0xDE, 0x7F, 0xE0, 0x68, 0x7F, 0x9D, 0x2E, 0x04, 0x0E, 0x88, 0xFF, 0xEF, 0xEF, 0x8A, 0xAF, 0x00, 0x8E, 0x47, 0x24, 0xDD, 0x78, 0xDD, 0x77, 0x33, 0x00, 0x11, 0x33, 0x11, 0x8D, 0x7D, 0x13, 0x13, 0x7D, 0xDF, 0x20, 0x03, 0x8A, 0xBF, 0x77, 0x50, 0x17, 0x70, 0x07, 0xFF, 0x49, 0x30, 0x2B, 0xB0, 0x2F, 0xDB, 0xF0, 0x0F, 0x01, 0xB9, 0x7F, 0xA8, 0x6D, 0xEA, 0x7F, 0x7F, 0x10, 0x6F, 0x7F, 0x27, 0xB0, 0xD0, 0x04, 0xA1, 0x00, 0x0D, 0xB0, 0x01, 0x02, 0x60, 0xED, 0x61, 0xFF, 0x2C, 0xFF, 0x1A, 0xBE, 0xFF, 0xF0, 0x3E, 0xB7, 0x00, 0xC0, 0xFF, 0x19, 0x00, 0x21, 0x1D, 0x01, 0x8C, 0x28, 0xFA, 0xCC, 0xFF, 0x3A, 0x3B, 0x92, 0x40, 0x3F, 0x17, 0xFF, 0x46, 0x6B, 0x27, 0x4C, 0x84, 0xFF, 0xE9, 0xBD, 0xB9, 0x3C, 0xB8, 0xFD, 0xF1, 0x23, 0x34, 0x30, 0x62, 0x4C, 0xDA, 0x40, 0x13, 0xF7, 0xFF, 0xF1, 0x20, 0x03, 0x04, 0xEF, 0xFF, 0xE8, 0xFF, 0xE0, 0x20, 0x03, 0xE1, 0xFF, 0x1C, 0xD9, 0xFF, 0xD3, 0x50, 0x95, 0x2E, 0xE1, 0x21, 0x87, 0x57, 0xFF, 0x1A, 0x86, 0xFF, 0xD1, 0x93, 0x69, 0x30, 0x41, 0xFA, 0x31, 0x9F, 0xAC, 0x22, 0xFF, 0xC7, 0x41, 0xA5, 0xD9, 0xFF, 0xE4, 0x50, 0x5B, 0xF6, 0x20, 0xFF, 0xF2, 0x20, 0x5D, 0xFB, 0xFF, 0xEE, 0xFF, 0xEA, 0xAA, 0x2F, 0x23, 0xF5, 0x20, 0x05, 0xE4, 0x23, 0x97, 0xEA, 0x2E, 0x2E, 0xDA, 0x08, 0xFF, 0xDB, 0xFF, 0xD5, 0x2C, 0x6E, 0xC6, 0xFF, 0xD0, 0x02, 0xFF, 0xCB, 0xFF, 0xC1, 0xFF, 0xBC, 0x27, 0xE7, 0xE1, 0xA0, 0x20, 0x11, 0xD2, 0x24, 0x7A, 0xDA, 0xFF, 0xCD, 0xFF, 0xCA, 0x82, 0x20, 0x19, 0xC1, 0xFF, 0xB7, 0xFF, 0xB3, 0x20, 0xFE, 0xBA, 0x0A, 0xFF, 0xAF, 0xFF, 0xAB, 0x05, 0xD1, 0xFF, 0x5F, 0x62, 0x6D, 0x03, 0x28, 0xFF, 0x29, 0x20, 0xC2, 0xC2, 0xE1, 0x7F, 0x05, 0xFF, 0x9F, 0xAD, 0x22, 0x8D, 0x07, 0x21, 0x61, 0xA7, 0x20, 0x9A, 0x5F, 0xE9, 0x8A, 0xD9, 0x48, 0xA8, 0x38, 0x99, 0xFE, 0x41, 0x01, 0xF7, 0x25, 0x34, 0xEA, 0xFF, 0xE0, 0x51, 0x8D, 0xD1, 0x73, 0xF6, 0x80, 0x27, 0xF7, 0xFF, 0xEB, 0x25, 0x56, 0x54, 0xE0, 0x21, 0x1D, 0xE9, 0x21, 0x25, 0xDE, 0x2F, 0x4A, 0xD4, 0xFF, 0x14, 0xD3, 0xFF, 0xC9, 0x2F, 0x52, 0xD3, 0x2B, 0x3D, 0xC9, 0xFF, 0x54, 0xC8, 0x25, 0x49, 0xBD, 0x21, 0x07, 0xFC, 0x27, 0x46, 0xF0, 0xFF, 0x51, 0xE6, 0x20, 0x2D, 0xE2, 0x25, 0x9E, 0xD5, 0xFF, 0xE3, 0x21, 0x95, 0x55, 0xD6, 0x2D, 0xB0, 0xD0, 0x20, 0x21, 0xC3, 0x25, 0x10, 0xDA, 0x21, 0x3B, 0x14, 0xCD, 0xFF, 0xC5, 0x21, 0x4D, 0xC4, 0x25, 0x7B, 0xB6, 0xFF, 0x40, 0xBF, 0x21, 0x3D, 0xB2, 0xFF, 0xAB, 0xFF, 0xB0, 0xFF, 0x05, 0xA9, 0xFF, 0xA3, 0xFF, 0x9C, 0x21, 0x51, 0xC0, 0x22, 0x4A, 0x54, 0xB5, 0x21, 0x53, 0xAE, 0x21, 0xA8, 0xA2, 0x21, 0x59, 0xAA, 0xFF, 0x50, 0xA8, 0x20, 0xC8, 0xA0, 0x2F, 0xE0, 0x95, 0xFF, 0x8C, 0xFF, 0x40, 0xA6, 0x2B, 0x49, 0x9A, 0xFF, 0x92, 0xFF, 0x96, 0xFF, 0x54, 0x8F, 0x25, 0x33, 0x84, 0x20, 0x05, 0x87, 0x22, 0x2C, 0x7C, 0xFF, 0x15, 0x7F, 0xFF, 0x79, 0x2B, 0x43, 0x6E, 0x22, 0x86, 0xB8, 0x20, 0x4B, 0x46, 0xAA, 0x20, 0x53, 0xAD, 0xFF, 0xA4, 0x21, 0x00, 0x30, 0x53, 0x96, 0x2A, 0xFF, 0x90, 0x2B, 0xFF, 0x92, 0x20, 0xFC, 0x85, 0x20, 0x4B, 0xA4, 0x20, 0xFF, 0x9B, 0x20, 0x3D, 0xA0, 0xFF, 0x9D, 0xFF, 0x93, 0x82, 0x20, 0x17, 0x8D, 0xFF, 0x89, 0xFF, 0x80, 0x20, 0x3F, 0x86, 0x28, 0xFF, 0x83, 0x20, 0x41, 0x76, 0x20, 0x0D, 0x83, 0xFF, 0x7D, 0x0A, 0xFF, 0x77, 0xFF, 0x7E, 0x20, 0x4F, 0x72, 0x25, 0x87, 0x72, 0x02, 0xFF, 0x6C, 0xFF, 0x67, 0xFF, 0x62, 0x40, 0x03, 0x5C, 0x00, 0xFF, 0x58, 0xFF, 0x74, 0xFF, 0x70, 0xFF, 0x69, 0x28, 0xFF, 0x65, 0x25, 0xA1, 0x6A, 0x20, 0x15, 0x5F, 0xFF, 0x5E, 0x02, 0xFF, 0x5A, 0xFF, 0x53, 0xFF, 0x50, 0x22, 0x6C, 0x54, 0x0A, 0xFF, 0x4D, 0xFF, 0x4A, 0x00, 0xD3, 0xFF, 0x16, 0x24, 0x1D, 0x6B, 0x35, 0xFF, 0x15, 0x22, 0x66, 0x72, 0xD7, 0x85, 0x2F, 0xA8, 0xED, 0x5F, 0x95, 0x55, 0xF9, 0x2E, 0xCE, 0xF0, 0x94, 0x3F, 0x75, 0x21, 0xBF, 0xD5, 0x84, 0x4D, 0x6A, 0x3D, 0x2F, 0xD0, 0xAF, 0xAC, 0xFD, 0x22, 0xFB, 0xE8, 0x26, 0x3B, 0xE0, 0xAA, 0x2F, 0xE7, 0xF8, 0x2F, 0x06, 0xF1, 0x23, 0x03, 0xD9, 0x23, 0x01, 0xD3, 0xAA, 0x21, 0x7F, 0xF0, 0x28, 0xC8, 0xE6, 0x21, 0x77, 0xD6, 0x23, 0x0F, 0xCC, 0xAA, 0x22, 0xD1, 0xDD, 0x21, 0x89, 0xD5, 0x22, 0xBF, 0xC3, 0x22, 0xF6, 0xBB, 0xAA, 0x22, 0xB1, 0xBF, 0x21, 0x61, 0xB5, 0x22, 0xB1, 0xA8, 0x21, 0x59, 0x9F, 0xAA, 0x22, 0xBB, 0xAB, 0x21, 0x69, 0xA2, 0x21, 0x5F, 0x95, 0x2D, 0x23, 0x8C, 0xAD, 0x42, 0xD5, 0xD2, 0x21, 0x9F, 0xBF, 0x21, 0x95, 0x30, 0x1B, 0xCB, 0x27, 0x21, 0x55, 0xC4, 0x21, 0xA7, 0xB0, 0x21, 0x9D, 0xA9, 0x21, 0x9F, 0xA6, 0x21, 0x7D, 0x55, 0x9E, 0x21, 0x7F, 0x8F, 0x23, 0xA2, 0x87, 0x21, 0x77, 0x96, 0x26, 0xB9, 0xA8, 0x30, 0x0B, 0x7F, 0x21, 0x19, 0x78, 0x21, 0x7F, 0x9E, 0xFF, 0x94, 0xA2, 0x20, 0x01, 0x8A, 0x26, 0xCF, 0x82, 0xFF, 0x81, 0x20, 0x11, 0x8B, 0xB1, 0x20, 0x05, 0x82, 0x20, 0x19, 0x30, 0x1B, 0x6E, 0xFF, 0x66, 0x21, 0xA5, 0x51, 0x71, 0x21, 0x41, 0x68, 0x21, 0x3D, 0x63, 0xFF, 0x60, 0x21, 0x3B, 0x50, 0x66, 0x21, 0x41, 0x5E, 0x2D, 0xBD, 0x57, 0xFF, 0x51, 0xFF, 0x15, 0x4F, 0xFF, 0x48, 0x21, 0xC5, 0x70, 0x20, 0x21, 0x68, 0x80, 0x17, 0x55, 0x6A, 0x20, 0x25, 0x63, 0x21, 0x63, 0x57, 0x20, 0x1D, 0x50, 0x20, 0x1F, 0x10, 0x55, 0xFF, 0x4E, 0x20, 0x01, 0x46, 0xFF, 0x47, 0xFF, 0x05, 0x40, 0xFF, 0x3F, 0xFF, 0x39, 0x20, 0x07, 0x3F, 0x20, 0x09, 0x51, 0x39, 0x20, 0x09, 0x32, 0x20, 0x01, 0x2C, 0xFF, 0x5D, 0x23, 0xF6, 0x60, 0x53, 0x20, 0x23, 0x30, 0x03, 0x49, 0xFF, 0x44, 0xFF, 0x4B, 0x08, 0xFF, 0x45, 0xFF, 0x42, 0x21, 0x3E, 0x40, 0xFF, 0x3C, 0x02, 0xFF, 0x38, 0xFF, 0x34, 0xFF, 0x4A, 0x20, 0x39, 0x41, 0xA8, 0x21, 0x4E, 0x43, 0x20, 0x05, 0x3B, 0x20, 0x11, 0x38, 0xFF, 0x35, 0x00, 0xFF, 0x31, 0xFF, 0x2E, 0xFF, 0x33, 0xFF, 0x30, 0x2A, 0xFF, 0x2B, 0x23, 0x46, 0x3B, 0x20, 0x0F, 0x33, 0x20, 0x0F, 0x30, 0x82, 0x24, 0xD2, 0x2A, 0xFF, 0x26, 0xFF, 0x2D, 0x2B, 0x94, 0x27, 0x80, 0x2D, 0xA5, 0x23, 0xFF, 0x20, 0xFF, 0x1E, 0xFF, 0x1B, 0xA8, 0x23, 0x68, 0x26, 0x40, 0x0B, 0x24, 0x2D, 0xB9, 0x1E, 0xFF, 0x1C, 0x02, 0xFF, 0x1D, 0xFF, 0x1A, 0xFF, 0x18, 0x21, 0xD2, 0x18, 0x8A, 0x24, 0xB8, 0x13, 0xFF, 0x12, 0x33, 0x8B, 0x00, 0x20, 0x36, 0xD2, 0xDA, 0x6B, 0xF6, 0x34, 0x85, 0x00, 0x24, 0x87, 0x64, 0xB3, 0xFA, 0x2C, 0x0B, 0xEA, 0xAA, 0x24, 0x61, 0xE4, 0x24, 0x57, 0xCC, 0x24, 0x59, 0xC6, 0x27, 0xFF, 0xDF, 0xA9, 0x24, 0x75, 0xDA, 0x24, 0x5F, 0xC1, 0x24, 0x4D, 0xBC, 0x00, 0x22, 0xB6, 0x62, 0x00, 0x23, 0x56, 0x43, 0x7B, 0xFE, 0xFF, 0xF2, 0x34, 0xA5, 0x00, 0xD5, 0x23, 0x4E, 0x24, 0xFD, 0xED, 0x2A, 0x35, 0xEA, 0x2C, 0x67, 0xD5, 0x24, 0xE9, 0x55, 0xD2, 0x24, 0x91, 0xB7, 0x24, 0x8F, 0xB2, 0x29, 0x02, 0xCD, 0x24, 0xA5, 0x55, 0xCA, 0x25, 0x7E, 0xAF, 0x24, 0x81, 0xAB, 0x25, 0x86, 0xB0, 0x23, 0x01, 0x55, 0xAA, 0x23, 0x4B, 0x96, 0x23, 0x4D, 0x90, 0x23, 0x5B, 0xA4, 0x23, 0x09, 0x55, 0x9F, 0x2E, 0xFF, 0x8A, 0x23, 0x35, 0x85, 0x22, 0xED, 0x7D, 0x22, 0xE9, 0x55, 0x77, 0x22, 0xDB, 0x67, 0x22, 0xD9, 0x62, 0x22, 0xE7, 0x72, 0x23, 0x39, 0x55, 0x6D, 0x22, 0xE3, 0x5C, 0x22, 0xE5, 0x57, 0x23, 0x6B, 0x9A, 0x23, 0x37, 0x55, 0x96, 0x23, 0x17, 0x80, 0x23, 0x19, 0x7C, 0x23, 0x77, 0x93, 0x23, 0x29, 0x55, 0x90, 0x25, 0x4A, 0x79, 0x23, 0x21, 0x76, 0x22, 0xFF, 0x6A, 0x23, 0x01, 0x55, 0x65, 0x24, 0x7A, 0x53, 0x22, 0xF9, 0x50, 0x28, 0xA9, 0x62, 0x23, 0x09, 0x55, 0x5F, 0x25, 0x6C, 0x4D, 0x23, 0x01, 0x4A, 0x21, 0x7F, 0x53, 0x25, 0x78, 0x51, 0x4E, 0x21, 0x77, 0x42, 0x21, 0x79, 0x3D, 0xFF, 0x52, 0x21, 0x85, 0x55, 0x4E, 0x21, 0x87, 0x40, 0x21, 0x7D, 0x3C, 0x21, 0x7F, 0x3A, 0x21, 0x69, 0x55, 0x35, 0x21, 0x6F, 0x2D, 0x25, 0xA4, 0x28, 0x2E, 0xFD, 0x30, 0x21, 0x65, 0x55, 0x2C, 0x41, 0x53, 0x1E, 0x21, 0x61, 0x1B, 0x21, 0x9F, 0x41, 0x21, 0xDD, 0x55, 0x3D, 0x21, 0xAB, 0x31, 0x21, 0x99, 0x2D, 0x21, 0xA7, 0x3B, 0x21, 0xAF, 0x55, 0x38, 0x21, 0x9F, 0x2B, 0x21, 0xA1, 0x29, 0x24, 0xE8, 0x23, 0x21, 0x95, 0x55, 0x20, 0x21, 0x77, 0x18, 0x21, 0x79, 0x15, 0x21, 0x87, 0x1E, 0x2F, 0x43, 0x55, 0x1C, 0x21, 0x83, 0x13, 0x23, 0x5E, 0x12, 0x2F, 0x4F, 0x1D, 0x40, 0x1B, 0x45, 0x19, 0x23, 0x6C, 0x14, 0xFF, 0x11, 0x26, 0x72, 0x14, 0x23, 0x76, 0x54, 0x11, 0x20, 0x09, 0x0E, 0x20, 0x01, 0x0B, 0x21, 0xA3, 0x10, 0xFF, 0x10, 0x0F, 0xFF, 0x0D, 0x40, 0x03, 0x0B, 0xFF, 0x0A, 0xFF, 0x55, 0x0C, 0x20, 0x03, 0x09, 0x25, 0x24, 0x08, 0x25, 0x28, 0x06, 0x25, 0x32, 0x55, 0x13, 0x20, 0x1D, 0x10, 0x20, 0x1F, 0x0C, 0x20, 0x15, 0x0A, 0x25, 0x3C, 0x55, 0x0F, 0x20, 0x33, 0x0D, 0x20, 0x27, 0x08, 0x20, 0x1D, 0x07, 0x25, 0x52, 0xAB, 0x50, 0x25, 0x04, 0x20, 0x01, 0x03, 0x25, 0x76, 0x02, 0x80, 0x07, 0x50, 0x01, 0x56, 0x01, 0x00, 0xB9, 0x7F, 0x20, 0x2C, 0x1D, 0x03, 0x04, 0xE9, 0x7F, 0x10, 0x04, 0x80, 0x59, 0x30, 0x18, 0xC2, 0xFE, 0xE2, 0x2C, 0x3A, 0x3A, 0x46, 0x20, 0xF8, 0xE9, 0x06, 0xFF, 0x00, 0x95, 0x00, 0xDC, 0x00, 0x3E, 0x2E, 0x03, 0x1F, 0xA9, 0x80, 0x0C, 0xF2, 0x00, 0x10, 0xF9, 0x38, 0xEF, 0x4F, 0x02, 0x50, 0x90, 0x0F, 0xFF, 0xFF, 0xC0, 0xD0, 0x00, 0xDE, 0x98, 0xBF, 0x1B, 0xCB, 0xFF, 0x2F, 0x23, 0xF0, 0xF2, 0x7F, 0x4B, 0xFF, 0x01, 0xCF, 0x27, 0x10, 0x39, 0xE0, 0x2B, 0x80, 0x11, 0xCD, 0x90, 0x00, 0x90, 0x09, 0x08, 0x01, 0x9C, 0x00, 0x00, 0xB2, 0x00, 0x10, 0x0A, 0x0E, 0x90, 0x90, 0x08, 0x08, 0x90, 0x00, 0x80, 0x09, 0xBD, 0x00, 0x20, 0x2D, 0x1E, 0xB1, 0x00, 0x9C, 0x0A, 0x00, 0x01, 0x5B, 0x00, 0x00, 0x13, 0x10, 0x49, 0x00, 0xC3, 0x35, 0xC7, 0x02, 0xBA, 0x40, 0xA2, 0x00, 0x4B, 0x5B, 0xC7, 0x80, 0x5C, 0x4B, 0x13, 0xC5, 0x00, 0x21, 0xAC, 0x41, 0x31, 0xC0, 0xCA, 0x37, 0x13, 0x02, 0x00, 0x06, 0x00, 0x00, 0x0D, 0x7F, 0x30, 0x1F, 0x01, 0x00, 0x3B, 0x01, 0x3C, 0x13, 0x3A, 0x0C, 0x0C, 0xE4, 0x00, 0xC4, 0x0D, 0x8D, 0xC4, 0xB4, 0x01, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x3B, 0x00, 0x86, 0x00, 0x04, 0x00, 0x97, 0xD6, 0x11, 0xDA, 0x4F, 0xFF, 0x07, 0x00, 0x00, 0x4B, 0xB7, 0x87, 0x20, 0x00, 0xA7, 0xC6, 0x20, 0x00, 0xCA, 0x1E, 0x3C, 0x4C, 0x4B, 0x1E, 0x08, 0x5C, 0x40, 0xD6, 0x47, 0xD9, 0x60, 0x00, 0x58, 0x00, 0x26, 0x00, 0x00, 0x00, 0x5C, 0xCE, 0x00, 0x41, 0x70, 0x70, 0x0A, 0x00, 0x0A, 0x90, 0xCA, 0x0A, 0x08, 0x4C, 0x3C, 0xC0, 0x04, 0xE1, 0x4C, 0xC8, 0xD0, 0x52, 0x37, 0xFE, 0x21, 0xBC, 0x20, 0x00, 0x0A, 0x36, 0x47, 0x00, 0xB1, 0x22, 0xBB, 0x13, 0x00, 0xA9, 0x7C, 0x49, 0x03, 0xAC, 0x23, 0x3C, 0xA8, 0x00, 0x5B, 0x30, 0x00, 0x99, 0xC1, 0x20, 0xAA, 0x01, 0x04, 0x1C, 0x00, 0x00, 0x1D, 0x1E, 0x28, 0x3E, 0x90, 0x00, 0x02, 0x07, 0x90, 0x90, 0x27, 0xBD, 0x1D, 0x20, 0x0F, 0x1E, 0x85, 0x20, 0x13, 0x90, 0x90, 0x0A, 0x06, 0x20, 0xC7, 0xAC, 0x38, 0x3E, 0x08, 0x01, 0x5D, 0x00, 0xB3, 0x68, 0x41, 0x2B, 0xD4, 0xD0, 0x00, 0xD0, 0x70, 0xD3, 0x6D, 0x10, 0x00, 0x33, 0x8A, 0x0B, 0x0C, 0x08, 0xDD, 0xD9, 0x0F, 0x35, 0xD8, 0x11, 0x49, 0x5C, 0x39, 0x77, 0xAF, 0x89, 0x65, 0x10, 0x60, 0x14, 0x11, 0x30, 0x1C, 0x39, 0x89, 0x22, 0x03, 0xD0, 0x32, 0xB5, 0x80, 0x1F, 0x21, 0x00, 0x50, 0x52, 0xA0, 0x3F, 0x22, 0x69, 0xBC, 0x20, 0x00, 0x40, 0x3F, 0xEF, 0x77, 0x5A, 0xA0, 0x1D, 0xC0, 0x5F, 0x31, 0x89, 0xFA, 0xA0, 0x81, 0xC0, 0x5F, 0x7A, 0x1B, 0x93, 0x00, 0x70, 0x5F, 0x20, 0xB0, 0x3A, 0x42, 0x7C, 0x09, 0x00, 0x40, 0xBF, 0xC0, 0xF6, 0xA0, 0x0C, 0x2A, 0x65, 0x40, 0x43, 0x37, 0x30, 0xE3, 0xFF, 0x20, 0xF9, 0x00, 0xB7, 0xFF, 0xFF, 0xAF, 0xCF, 0x03, 0xD1, 0xF8, 0x02, 0xFF, 0x7F, 0xFE, 0xFF, 0x0C, 0x05, 0x23, 0xB6, 0x50, 0x80, 0x23, 0x34, 0x80, 0xED, 0xFF, 0xEE, 0xFF, 0x79, 0x00, 0x14, 0x77, 0x00, 0xEE, 0x20, 0x07, 0x77, 0x20, 0x07, 0x00, 0xAA, 0x02, 0x00, 0x07, 0xFF, 0xFF, 0x3F, 0xCF, 0x2B, 0x90, 0xA5, 0x0C, 0x00, 0x00, 0xF9, 0xF8, 0x70, 0x17, 0x80, 0x1F, 0x4A, 0x00, 0x00, 0xA0, 0x6F, 0x6F, 0xF0, 0x30, 0x00, 0x9B, 0x00, 0x0F, 0x00, 0xEF, 0x23, 0x00, 0x80, 0x37, 0x80, 0x3F, 0xEA, 0x05, 0x00, 0x30, 0x1F, 0x17, 0x80, 0xE8, 0xAB, 0x59, 0xF7, 0x59, 0x00, 0x60, 0x3F, 0x52, 0x72, 0x4B, 0xF4, 0xC0, 0x00, 0xE0, 0x5F, 0x00, 0x90, 0x7F, 0xA2, 0x00, 0x6A, 0xF4, 0xF3, 0x9F, 0x54, 0x8F, 0x90, 0xBF, 0xDE, 0x20, 0xDF, 0x97, 0xDC, 0x48, 0x01, 0x20, 0x00, 0x10, 0x7B, 0xFF, 0x02, 0xAF, 0xFC, 0x30, 0xFF, 0x40, 0xFA, 0x39, 0xE3, 0x4E, 0xFF, 0x00, 0x04, 0x00, 0x65, 0x00, 0x50, 0x01, 0xA9, 0x88, 0x05, 0x04, 0xFF, 0xF6, 0x04, 0x1E, 0x8F, 0xB0, 0x50, 0xEF, 0x00, 0x4A, 0x9F, 0x01, 0x05, 0x96, 0x08, 0x3C, 0x8F, 0x70, 0x90, 0x25, 0x04, 0x70, 0xA1, 0xFA, 0x43, 0xB8, 0xFF, 0x19, 0xEF, 0x02, 0x00, 0x20, 0xC5, 0x2A, 0xD9, 0x80, 0x80, 0x30, 0x03, 0x01, 0xFF, 0xFE, 0x05, 0x0B, 0xF8, 0xE1, 0x6F, 0x2B, 0x97, 0x02, 0x80, 0x90, 0x00, 0x05, 0x60, 0x00, 0x2F, 0x66, 0xB6, 0x00, 0xFF, 0xFF, 0x25, 0x06, 0x06, 0x1F, 0xF8, 0xF8, 0x11, 0x9F, 0xF8, 0xF7, 0x2F, 0x73, 0x06, 0x07, 0xBB, 0x21, 0x06, 0x20, 0xD0, 0x40, 0x3B, 0xBB, 0xB8, 0x00, 0x6F, 0x6F, 0x70, 0x00, 0xF0, 0x6F, 0x6F, 0xE0, 0xE0, 0x68, 0xDF, 0x50, 0x04, 0xA0, 0xDF, 0xDF, 0x90, 0x90, 0x20, 0x0B, 0xF0, 0x4B, 0x10, 0x00, 0xB0, 0x00, 0x20, 0x0B, 0xA0, 0x9B, 0x00, 0x70, 0x00, 0x00, 0x89, 0xFF, 0xB6, 0x8D, 0xFF, 0xFF, 0x04, 0x00, 0x03, 0xAD, 0xFD, 0x23, 0x2F, 0xF3, 0xF3, 0x9F, 0x48, 0xAF, 0x20, 0x0B, 0x04, 0xBB, 0x2D, 0xB5, 0xF3, 0xF3, 0xAF, 0x00, 0xBF, 0xB2, 0x00, 0x8B, 0x00, 0xE8, 0xB0, 0xFF, 0x00, 0xEF, 0xC0, 0xC0, 0xFF, 0xFF, 0x49, 0x10, 0x81, 0x18, 0xFD, 0x90, 0xC1, 0x2B, 0x9B, 0x20, 0x0B, 0x90, 0x00, 0xBB, 0x02, 0x00, 0xA0, 0x21, 0xFF, 0xFF, 0x01, 0x25, 0x96, 0xCC, 0x00, 0x07, 0x7C, 0xFA, 0x68, 0xAC, 0xFB, 0x89, 0x00, 0x00, 0x0A, 0x95, 0xFA, 0x5F, 0x48, 0xF8, 0xF9, 0x03, 0x00, 0x06, 0x72, 0xFA, 0xBD, 0x21, 0x9D, 0x01, 0x17, 0x00, 0x0D, 0xF9, 0xF9, 0x01, 0x00, 0xB7, 0x00, 0x58, 0x00, 0xDF, 0xDB, 0xD8, 0x4F, 0x3F, 0x30, 0x20, 0x3A, 0x00, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x38, 0x6A, 0x4F, 0x08, 0x4F, 0x20, 0x30, 0x3B, 0x2E, 0x19, 0xFF, 0xFF, 0x4A, 0x20, 0x0B, 0xBB, 0x2E, 0x18, 0x70, 0xFA, 0xCC, 0x5E, 0xFF, 0x00, 0xFF, 0x09, 0x08, 0xFA, 0xFA, 0x8F, 0x8F, 0xF3, 0x00, 0xF3, 0x8F, 0x7F, 0xFF, 0xFC, 0x08, 0x3D, 0x91, 0x00, 0x00, 0xDD, 0x00, 0xF3, 0xF9, 0x8F, 0x9F, 0xBA, 0x00, 0x00, 0x6B, 0x00, 0x00, 0xB0, 0xC7, 0xAF, 0xF4, 0x00, 0xF7, 0x6F, 0x7F, 0xDC, 0x70, 0x19, 0xDF, 0x30, 0x00, 0x30, 0xFF, 0xFF, 0xF5, 0xC0, 0x6F, 0x9F, 0x10, 0x00, 0x00, 0xD8, 0x00, 0x30, 0x60, 0xFF, 0xEF, 0xDB, 0x09, 0x12, 0x2A, 0x00, 0x31, 0x2E, 0x70, 0x09, 0x0C, 0x36, 0x5C, 0x01, 0xFF, 0xFE, 0x00, 0x10, 0xFD, 0xFF, 0x09, 0x5B, 0xEB, 0x10, 0x40, 0x40, 0xB0, 0x20, 0x2B, 0xFF, 0x9F, 0x1E, 0x08, 0xA8, 0x24, 0x37, 0x09, 0xAE, 0x7F, 0x05, 0x09, 0xE4, 0x31, 0x40, 0x00, 0xFF, 0x40, 0xE4, 0x3F, 0x49, 0x9F, 0xFF, 0x02, 0xBF, 0xFA, 0x30, 0x3B, 0xFF, 0xC8, 0x00, 0x0F, 0x49, 0x23, 0xFC, 0x24, 0x02, 0xEE, 0x24, 0x02, 0x40, 0x07, 0xFD, 0xC5, 0xFA, 0x3F, 0x7B, 0x60, 0x17, 0x70, 0x1F, 0x00, 0x05, 0x7A, 0x09, 0x90, 0x1F, 0x87, 0xD0, 0xBF, 0x80, 0x56, 0xF1, 0x20, 0xFB, 0xF9, 0xFF, 0xFF, 0x8C, 0xAF, 0x08, 0x03, 0xFF, 0x5E, 0x04, 0x10, 0x16, 0x4D, 0xE6, 0x43, 0x4C, 0x49, 0x08, 0x4D, 0xFF, 0xFE, 0x14, 0x2F, 0xFF, 0x02, 0x02, 0x28, 0xC2, 0x29, 0x6A, 0x39, 0x87, 0x69, 0x6D, 0x61, 0x67, 0x39, 0x75, 0x80, 0xA0, 0x27, 0xBE, 0x0D, 0x67, 0x0F, 0x6C, 0x1E, 0xCE, 0x25, 0x67, 0x00, 0xD5, 0x3B, 0x50, 0x41, 0x4B, 0x55, 0x53, 0xBB, 0x00, 0xB5, 0xA2, 0xE7, 0x03, 0x3F, 0x61, 0x30, 0xD2, 0x00, 0x45, 0x8F, 0x3B, 0x58, 0x49, 0xCA, 0xF6, 0xA4, 0x00, 0x24, 0x2D, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char iQue_with_ISBN_LZ[0x2000] =
+{
+ 0x11, 0x48, 0x70, 0x00, 0x00, 0x64, 0x61, 0x72, 0x63, 0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x28, 0x70, 0x00, 0x00, 0x83, 0x30, 0x09, 0x1C, 0x04, 0x00, 0x00, 0x40, 0x20, 0x03, 0x30, 0x13, 0xAB, 0x30, 0x18, 0x15, 0x20, 0x1D, 0x02, 0xA0, 0x0B, 0x06, 0x20, 0x2B, 0x30, 0x18, 0x5A, 0x09, 0x20, 0x35, 0x10, 0x20, 0x39, 0x30, 0x2B, 0x48, 0x20, 0x29, 0x54, 0x82, 0x20, 0x45, 0xA0, 0x05, 0x00, 0x00, 0x30, 0x20, 0x35, 0x98, 0xAA, 0x20, 0x51, 0xE0, 0x20, 0x28, 0x3C, 0x20, 0x41, 0xDC, 0x20, 0x5D, 0x20, 0x07, 0x08, 0x00, 0x00, 0xCC, 0x0C, 0x20, 0x07, 0x30, 0x51, 0x20, 0x50, 0x50, 0x54, 0x20, 0x0B, 0x64, 0x20, 0x5D, 0x60, 0x21, 0x00, 0x00, 0x4C, 0x4C, 0x20, 0x5C, 0xA8, 0x01, 0x50, 0x53, 0x20, 0x22, 0x00, 0xB2, 0x82, 0x20, 0x75, 0xC0, 0x23, 0x00, 0x00, 0x94, 0x20, 0x2F, 0xE2, 0xB3, 0x30, 0x23, 0x30, 0x20, 0x47, 0x20, 0x68, 0x12, 0x02, 0x50, 0x77, 0x30, 0x8F, 0x41, 0x1C, 0x20, 0x90, 0x00, 0x41, 0x00, 0x00, 0x28, 0x20, 0xAB, 0x4E, 0x3E, 0x20, 0x9C, 0x80, 0x45, 0x20, 0x0B, 0x30, 0x4F, 0x30, 0x17, 0x47, 0xAD, 0x50, 0x17, 0x82, 0x30, 0x17, 0x4B, 0x20, 0x23, 0x20, 0x7B, 0xA4, 0x30, 0x2F, 0xAA, 0x20, 0xA0, 0xA8, 0x20, 0xE9, 0xC4, 0x30, 0x3B, 0x55, 0x50, 0x17, 0xDC, 0xB5, 0x30, 0x3B, 0x5D, 0x20, 0x47, 0x20, 0xE0, 0xF4, 0x30, 0x53, 0x60, 0x20, 0x53, 0x90, 0x30, 0xD4, 0x00, 0x2E, 0x21, 0x13, 0x61, 0x00, 0x6E, 0x00, 0x14, 0x69, 0x00, 0x6D, 0x21, 0x1D, 0x4E, 0x20, 0x07, 0x6E, 0x00, 0x10, 0x74, 0x00, 0x65, 0x20, 0x11, 0x64, 0x00, 0x6F, 0x00, 0x51, 0x4C, 0x20, 0x03, 0x67, 0x20, 0x07, 0x5F, 0x00, 0x44, 0x20, 0x03, 0x41, 0x30, 0x20, 0x01, 0x5F, 0x00, 0x53, 0x00, 0x63, 0x40, 0x1F, 0x05, 0x65, 0x00, 0x4F, 0x00, 0x75, 0x20, 0x2B, 0x41, 0x20, 0x43, 0x5A, 0x62, 0x20, 0x13, 0x6C, 0x40, 0x47, 0x02, 0x50, 0x43, 0x42, 0x03, 0x20, 0x43, 0x43, 0xBE, 0x01, 0x80, 0x87, 0x55, 0x03, 0x20, 0xCB, 0x00, 0x90, 0x43, 0x01, 0x90, 0xCB, 0x00, 0x90, 0x87, 0xF0, 0xCB, 0x62, 0xBF, 0x21, 0x5D, 0x79, 0x21, 0x97, 0x01, 0x31, 0xA1, 0x71, 0x8D, 0x00, 0xF0, 0x2F, 0x71, 0x05, 0xD0, 0x2F, 0x55, 0x74, 0x42, 0x09, 0x67, 0x23, 0x29, 0x33, 0x22, 0x01, 0x73, 0xA2, 0x01, 0xEA, 0xB0, 0x5B, 0x52, 0x2D, 0x00, 0x10, 0x21, 0x31, 0x01, 0x00, 0x21, 0x32, 0x01, 0x00, 0x43, 0x33, 0xA8, 0xE0, 0x65, 0x4C, 0x23, 0x71, 0x4D, 0x22, 0xA3, 0x73, 0x00, 0x6B, 0xFA, 0x00, 0x40, 0x85, 0x30, 0x1F, 0x00, 0xB0, 0x17, 0xF0, 0x93, 0xF2, 0xE3, 0x5F, 0x20, 0xB5, 0x32, 0x00, 0x00, 0x38, 0x00, 0x78, 0x00, 0x36, 0x00, 0x34, 0xC0, 0xE0, 0xE1, 0x70, 0x02, 0x43, 0x4C, 0x41, 0x4E, 0xFF, 0xFE, 0x58, 0x14, 0x34, 0x21, 0x02, 0x34, 0x03, 0x33, 0x96, 0x70, 0x61, 0x74, 0x34, 0x31, 0x3C, 0x64, 0x3E, 0x34, 0x59, 0x28, 0x33, 0x73, 0xFF, 0xFF, 0x40, 0xFF, 0x34, 0x4C, 0x53, 0x63, 0x65, 0x6E, 0x65, 0x4F, 0x20, 0x75, 0x74, 0x23, 0xBA, 0x00, 0x47, 0x5F, 0x41, 0x5F, 0x60, 0x30, 0x23, 0xDB, 0xB0, 0x01, 0x70, 0x61, 0x69, 0x31, 0xF8, 0xCA, 0x24, 0x8D, 0x50, 0x3F, 0x03, 0x00, 0x30, 0x59, 0x20, 0x24, 0x9D, 0x6C, 0xA0, 0x24, 0xA1, 0xAC, 0x24, 0xA5, 0x50, 0x5F, 0x4E, 0x69, 0x6E, 0x0E, 0x4C, 0x6F, 0x67, 0x6F, 0xA0, 0x39, 0x34, 0xA4, 0x34, 0xC1, 0x43, 0x11, 0x4C, 0x56, 0x43, 0x74, 0x43, 0x00, 0x10, 0x02, 0x40, 0x8B, 0xE4, 0x40, 0x0B, 0xD0, 0x61, 0x24, 0x35, 0x7F, 0x43, 0x34, 0xF0, 0x4E, 0x5F, 0x0E, 0x52, 0x6F, 0x6F, 0x74, 0xD0, 0x82, 0x00, 0x70, 0x4B, 0x80, 0x57, 0x00, 0x61, 0x20, 0x20, 0x3B, 0x70, 0x3F, 0x49, 0x53, 0x42, 0x4E, 0xD0, 0xBF, 0xFE, 0x02, 0x70, 0x8B, 0x00, 0x70, 0x03, 0xB1, 0x5F, 0x35, 0x57, 0xB1, 0x5F, 0x25, 0x32, 0x81, 0x5F, 0x00, 0x35, 0x00, 0x1E, 0x45, 0xAC, 0x71, 0x5F, 0x42, 0x41, 0x5F, 0x42, 0x00, 0x41, 0x5F, 0x73, 0xE0, 0x80, 0x2D, 0x91, 0x5F, 0x24, 0xF6, 0x00, 0xA0, 0x01, 0xE1, 0x5F, 0x91, 0x13, 0x2F, 0x34, 0xC2, 0x02, 0xD1, 0x53, 0xC8, 0x20, 0xAE, 0x02, 0x11, 0x53, 0x00, 0x30, 0x7F, 0x00, 0xB1, 0x3F, 0xF7, 0x36, 0x8B, 0xB2, 0x9F, 0x31, 0xD5, 0x72, 0x9F, 0x65, 0x23, 0xD1, 0xB2, 0x9F, 0x32, 0x20, 0x15, 0x47, 0x5F, 0x43, 0x00, 0x42, 0x9F, 0xEC, 0x27, 0x2D, 0x0F, 0xE2, 0x9F, 0xE6, 0x31, 0x3F, 0x01, 0xF2, 0x9F, 0x92, 0x53, 0x12, 0xC3, 0x02, 0x32, 0x93, 0x92, 0xDF, 0x80, 0x5F, 0xBF, 0x92, 0x47, 0x60, 0x33, 0x5A, 0x47, 0xBC, 0x02, 0x51, 0x4B, 0x90, 0x8B, 0xF3, 0xDF, 0xDA, 0x37, 0xBF, 0x03, 0x33, 0xDF, 0x7C, 0x28, 0x07, 0x54, 0x1F, 0x0D, 0x43, 0xDF, 0x48, 0xAB, 0x28, 0x7D, 0xB0, 0x28, 0x81, 0xA4, 0x28, 0x6D, 0x24, 0x28, 0x68, 0x37, 0xAB, 0x05, 0x30, 0x03, 0x00, 0x00, 0xBC, 0x20, 0x03, 0x24, 0x28, 0x8B, 0x54, 0x88, 0x28, 0x53, 0xEC, 0x28, 0x74, 0xB0, 0x28, 0x43, 0x74, 0x0A, 0x0B, 0x00, 0x00, 0x78, 0x0B, 0x33, 0xBB, 0x57, 0x00, 0x04, 0x3B, 0x38, 0x12, 0xA5, 0x34, 0x2B, 0x44, 0x44, 0x97, 0x50, 0x41, 0x84, 0x0B, 0x02, 0xF3, 0xBF, 0xC5, 0x74, 0xBB, 0x01, 0x13, 0xE3, 0x50, 0x5F, 0x33, 0x00, 0x80, 0x67, 0xB8, 0x60, 0x67, 0xD6, 0x20, 0xAA, 0x44, 0xA7, 0x38, 0x29, 0x45, 0x68, 0x60, 0x6F, 0x94, 0x7B, 0xA0, 0x96, 0x28, 0xA5, 0xA0, 0x40, 0x28, 0xA1, 0xBE, 0x25, 0x19, 0x23, 0x96, 0xA0, 0x4C, 0xC0, 0x49, 0x59, 0x06, 0x02, 0x24, 0xDD, 0x90, 0x23, 0x33, 0x33, 0x02, 0xB3, 0x3F, 0xFC, 0x2D, 0xEC, 0xBC, 0x70, 0x0B, 0x0A, 0x32, 0xD7, 0x23, 0x20, 0x0B, 0x30, 0x2F, 0x80, 0x3F, 0x49, 0x89, 0x07, 0xF1, 0x01, 0xD0, 0x2F, 0xF5, 0x0B, 0xB0, 0x6B, 0x39, 0xEC, 0x40, 0x9D, 0x1C, 0x30, 0x97, 0xBF, 0x62, 0x2B, 0xCC, 0x20, 0x9F, 0x30, 0x9B, 0x70, 0xF3, 0x25, 0x63, 0xE5, 0x99, 0x71, 0x5B, 0x70, 0x50, 0xF1, 0x5B, 0x2A, 0x19, 0xD5, 0x67, 0x70, 0xC1, 0xCD, 0xCC, 0x53, 0xCC, 0x20, 0xEB, 0x20, 0x24, 0x82, 0xF8, 0xC1, 0x00, 0x31, 0x67, 0x00, 0x15, 0x97, 0xE6, 0x30, 0x7F, 0x30, 0x2F, 0x71, 0x73, 0x44, 0x73, 0xF6, 0x18, 0x01, 0x90, 0x7F, 0x3C, 0x51, 0xC2, 0x20, 0x7F, 0x3E, 0x02, 0xD0, 0x7F, 0x52, 0x65, 0x64, 0x01, 0x70, 0xFF, 0xC2, 0xC1, 0xEB, 0x46, 0x1F, 0xC2, 0xB7, 0x6D, 0xDB, 0x20, 0x7F, 0x8C, 0xBA, 0x25, 0x82, 0x20, 0x00, 0x40, 0xFF, 0x91, 0xF7, 0xB6, 0xFB, 0x5C, 0x85, 0x03, 0x00, 0x20, 0x00, 0xB4, 0x35, 0xBE, 0x00, 0x92, 0x24, 0xE9, 0xC0, 0xAD, 0x60, 0x8B, 0x31, 0x00, 0x32, 0xE7, 0x5C, 0x00, 0x22, 0xE7, 0x92, 0x53, 0xF0, 0x2B, 0x1D, 0x7F, 0x20, 0x25, 0x97, 0x90, 0x0B, 0x50, 0x97, 0x35, 0x6B, 0x00, 0x50, 0x97, 0x97, 0x2F, 0x30, 0x3B, 0xAF, 0x77, 0xE4, 0xAA, 0xF1, 0x17, 0x32, 0x02, 0x13, 0x73, 0x32, 0xF7, 0x50, 0x8B, 0x00, 0x97, 0x57, 0xF9, 0x33, 0x1B, 0x58, 0x58, 0x00, 0x31, 0x7F, 0x3C, 0x70, 0x57, 0xE3, 0x54, 0x53, 0x2C, 0x4A, 0xB7, 0x48, 0x53, 0x4C, 0x38, 0x6B, 0x2C, 0xB9, 0x94, 0x63, 0x8B, 0x3C, 0x67, 0x3C, 0xB1, 0x61, 0x24, 0x4C, 0xB5, 0x00, 0x01, 0x97, 0xC0, 0x39, 0x8E, 0xE3, 0x28, 0x96, 0xE8, 0x51, 0x5B, 0x5C, 0xDD, 0x01, 0x20, 0x23, 0x03, 0xF8, 0x47, 0x40, 0x41, 0x9E, 0x11, 0x15, 0x8D, 0xBD, 0x31, 0xA3, 0x9A, 0x99, 0xB9, 0x23, 0xD7, 0xAA, 0x2D, 0x3A, 0x04, 0x01, 0x10, 0x23, 0x01, 0x01, 0x20, 0x8F, 0x01, 0x01, 0x20, 0x8F, 0x01, 0xAD, 0x00, 0x10, 0x8F, 0xC1, 0x20, 0x8F, 0x3D, 0x60, 0x8F, 0x44, 0x5B, 0x01, 0x00, 0x10, 0x8F, 0x82, 0x00, 0x00, 0x23, 0x50, 0x5F, 0x42, 0x6C, 0x6B, 0x03, 0xE1, 0x63, 0x9A, 0x03, 0x99, 0x19, 0xC0, 0x0E, 0x74, 0xDA, 0x00, 0xC1, 0x63, 0x00, 0x40, 0x23, 0xFE, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0x03, 0x81, 0x63, 0x00, 0x13, 0xBB, 0x00, 0x32, 0xC7, 0x58, 0xAB, 0x2F, 0x7D, 0x88, 0x66, 0x4F, 0xE8, 0x2F, 0x89, 0x18, 0x2F, 0x75, 0x3F, 0x4F, 0x7D, 0x78, 0x62, 0xC7, 0xE3, 0xD3, 0x56, 0x3F, 0x60, 0x0B, 0x52, 0xD3, 0xF0, 0xC2, 0xD3, 0xEE, 0x01, 0xC0, 0x2F, 0x22, 0xDF, 0xD4, 0x33, 0x40, 0x68, 0x3F, 0x50, 0x0B, 0x52, 0xEB, 0xF0, 0xFF, 0xC2, 0xEB, 0x01, 0xB0, 0x2F, 0x32, 0xF7, 0x01, 0xB0, 0xBF, 0x33, 0x03, 0x01, 0xC0, 0x2F, 0x00, 0x10, 0xBF, 0x46, 0x73, 0xFF, 0x70, 0x0B, 0x53, 0x1B, 0x40, 0xBF, 0x83, 0x1B, 0x01, 0xB0, 0x2F, 0x63, 0x27, 0x03, 0xC1, 0xC3, 0x33, 0x27, 0xFF, 0x75, 0x97, 0x93, 0x33, 0x00, 0x91, 0xC3, 0x01, 0x00, 0x2F, 0x05, 0xE1, 0xC3, 0x00, 0xF0, 0xBF, 0xF1, 0xC3, 0x01, 0x00, 0x2F, 0xFF, 0x05, 0x01, 0xC3, 0x00, 0x16, 0xB7, 0x00, 0x36, 0x4F, 0x35, 0xCC, 0x33, 0x8B, 0x36, 0x53, 0x33, 0x8F, 0x3D, 0x0F, 0xBF, 0x39, 0xE3, 0xD0, 0x6A, 0x5D, 0xE6, 0xCF, 0x59, 0xC7, 0x26, 0x43, 0x00, 0x40, 0x17, 0x26, 0x37, 0xFF, 0xD6, 0xFF, 0x63, 0x57, 0x26, 0x2B, 0x00, 0x30, 0x17, 0x36, 0x1F, 0x00, 0x30, 0x5F, 0x36, 0x13, 0x00, 0x40, 0x17, 0xFF, 0x00, 0x10, 0x5F, 0x49, 0x6B, 0x35, 0xFB, 0x00, 0x30, 0x17, 0x65, 0xEF, 0x03, 0xC1, 0x03, 0x82, 0xC7, 0xE1, 0x03, 0xFE, 0x82, 0xDF, 0x02, 0xE1, 0x03, 0x73, 0x27, 0xF1, 0x03, 0x80, 0x17, 0x01, 0xE1, 0x03, 0x00, 0xFF, 0x5F, 0x54, 0xDD, 0xEC, 0xDF, 0x02, 0x7F, 0x5F, 0x04, 0x2F, 0xF4, 0x5F, 0x8D, 0xDC, 0xDF, 0x50, 0x2F, 0xBF, 0x55, 0xB8, 0x2F, 0xC3, 0x20, 0x2F, 0xC4, 0xA0, 0x2F, 0xC8, 0x2C, 0x2C, 0xE3, 0x54, 0xAC, 0x2C, 0xE7, 0x10, 0x2C, 0xDF, 0x74, 0x2C, 0xDF, 0xD8, 0x07, 0xBF, 0x2D, 0x17, 0x09, 0x2F, 0x87, 0x2C, 0xE3, 0x02, 0x9C, 0xDF, 0x3F, 0x4B, 0x00, 0xFC, 0xDF, 0x9F, 0x6F, 0xAF, 0x00, 0xBC, 0xDF, 0x7C, 0xEC, 0xDF, 0x2C, 0x6D, 0x5B, 0xDD, 0x4F, 0x4C, 0xE3, 0x8C, 0xD3, 0xFF, 0xD0, 0x17, 0x9C, 0xBB, 0x00, 0x30, 0x17, 0x00, 0x9F, 0xCF, 0x3F, 0xFF, 0x01, 0x1C, 0x8B, 0x00, 0x0D, 0xE7, 0xC3, 0xA3, 0x7E, 0xA0, 0x2C, 0x7B, 0x00, 0x5C, 0x7F, 0xD0, 0x23, 0x01, 0x1C, 0x73, 0x03, 0xD0, 0x67, 0x02, 0x7C, 0x5B, 0x70, 0xDF, 0x2B, 0xCB, 0x7C, 0x5B, 0x20, 0x3B, 0xDB, 0x00, 0xED, 0x5B, 0x3E, 0x67, 0x7F, 0xC7, 0x5B, 0xCF, 0xDF, 0x00, 0xFC, 0x4F, 0x00, 0xDC, 0xDB, 0xF0, 0x2D, 0xCB, 0x80, 0x7F, 0x01, 0x2C, 0xDB, 0x30, 0x2F, 0x7F, 0xFB, 0x7F, 0xC8, 0x2F, 0x03, 0x7C, 0xDB, 0x5B, 0xE7, 0xAC, 0xDB, 0x00, 0x4C, 0x4F, 0x03, 0x3D, 0x67, 0x00, 0x1E, 0x67, 0xFF, 0xDD, 0x67, 0x04, 0x1C, 0x67, 0x41, 0xA3, 0x79, 0x93, 0x9D, 0x43, 0xCC, 0x67, 0x00, 0x60, 0x23, 0xCC, 0x67, 0xFF, 0x31, 0xEB, 0x89, 0x7B, 0x28, 0x2F, 0x00, 0x3C, 0x67, 0x00, 0x50, 0x23, 0xDC, 0x67, 0x00, 0x50, 0x8F, 0xDC, 0x67, 0xFE, 0x00, 0x60, 0x23, 0x00, 0x10, 0x8F, 0x79, 0x4B, 0x30, 0x8F, 0x00, 0x2C, 0x67, 0x00, 0x50, 0x23, 0x04, 0x1C, 0x67, 0x70, 0x7F, 0xC2, 0xA9, 0x33, 0x00, 0x81, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0xFF, 0x03, 0x81, 0x63, 0x01, 0x5C, 0x67, 0x01, 0x9F, 0x2F, 0x43, 0xEB, 0x6F, 0x2F, 0x9F, 0x97, 0xDF, 0x2F, 0x00, 0x60, 0x23, 0xFF, 0xCF, 0x2F, 0x34, 0x33, 0x7F, 0x2F, 0x38, 0x2F, 0x00, 0x3F, 0x2F, 0x00, 0x50, 0x23, 0xDF, 0x2F, 0x00, 0x50, 0x8F, 0xFF, 0xDF, 0x2F, 0x00, 0x60, 0x23, 0x00, 0x10, 0x8F, 0x6F, 0x2F, 0x40, 0x8F, 0x00, 0x2F, 0x2F, 0x00, 0x50, 0x23, 0x01, 0x7C, 0x07, 0xFF, 0x01, 0xB1, 0x63, 0x9F, 0x2F, 0x00, 0x91, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0xFF, 0x03, 0x81, 0x63, 0x01, 0x5B, 0xA7, 0x01, 0x95, 0x8F, 0x46, 0x27, 0x6F, 0x23, 0x9F, 0xDF, 0xD5, 0x8F, 0x00, 0x60, 0x23, 0xFF, 0xC5, 0x8F, 0x4F, 0xDF, 0x6F, 0x0B, 0x4F, 0xDF, 0x00, 0x25, 0x8F, 0x00, 0x50, 0x23, 0xD5, 0x8F, 0x00, 0x50, 0x8F, 0xFF, 0xD5, 0x8F, 0x00, 0x60, 0x23, 0x00, 0x10, 0x8F, 0x6E, 0xDB, 0x40, 0x8F, 0x00, 0x25, 0x8F, 0x00, 0x50, 0x23, 0x01, 0x7C, 0x07, 0xFF, 0x01, 0xB1, 0x63, 0x9E, 0xC3, 0x00, 0x91, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0xDE, 0x03, 0x61, 0x63, 0x00, 0x7C, 0x5F, 0x4C, 0x2C, 0x5C, 0xBC, 0x5F, 0x3E, 0x51, 0x7C, 0x5F, 0x65, 0x31, 0x00, 0x73, 0xCC, 0x5F, 0x3B, 0x9C, 0x47, 0x5F, 0x43, 0x00, 0x4C, 0x5F, 0x5E, 0xFC, 0x2E, 0xBB, 0x0F, 0x5B, 0x58, 0x4C, 0x5F, 0x3C, 0x82, 0x3B, 0xAB, 0xBC, 0xAA, 0x2F, 0xFF, 0xFC, 0x2F, 0xF8, 0x3C, 0x2E, 0xDB, 0x7C, 0x2E, 0xDF, 0xBC, 0xF9, 0x2E, 0xE3, 0x00, 0x3C, 0x47, 0x3E, 0xC7, 0x5E, 0xFB, 0x00, 0x7A, 0x3B, 0x80, 0xBF, 0x9A, 0x3B, 0x7B, 0x60, 0x88, 0xC7, 0x00, 0x3C, 0x2B, 0x00, 0x70, 0x4B, 0x9F, 0x2B, 0xCA, 0x2A, 0xB7, 0x00, 0x9B, 0xCB, 0xBE, 0x01, 0x10, 0x3F, 0xF2, 0xA0, 0x3F, 0x00, 0x1B, 0xA3, 0x01, 0xD0, 0x3F, 0x00, 0x29, 0xEF, 0x01, 0x00, 0xBF, 0x8E, 0xF7, 0x2B, 0x77, 0x70, 0xFF, 0x00, 0x27, 0x67, 0x01, 0x00, 0xFF, 0x24, 0xF0, 0x3F, 0xDF, 0x83, 0x01, 0x01, 0x3F, 0x65, 0x30, 0x00, 0x8E, 0xBB, 0x5E, 0xBF, 0x59, 0x54, 0x7E, 0xBF, 0x94, 0x2F, 0xF4, 0x86, 0x3E, 0x1F, 0x6C, 0x79, 0x74, 0x31, 0x3E, 0xD1, 0x4A, 0x9E, 0x00, 0x40, 0xA0, 0x2D, 0xE7, 0x70, 0x43, 0x74, 0x78, 0x6C, 0x31, 0xD8, 0x3F, 0xDF, 0x3F, 0xBF, 0x04, 0x2F, 0xFF, 0x2D, 0x55, 0x74, 0x65, 0x6E, 0x00, 0x64, 0x6F, 0x5F, 0x31, 0x32, 0x38, 0x78, 0x36, 0x01, 0x34, 0x2E, 0x62, 0x63, 0x6C, 0x69, 0x6D, 0x2F, 0xFF, 0x0C, 0x66, 0x6E, 0x6C, 0x31, 0x3E, 0x63, 0x70, 0x27, 0x63, 0x62, 0x04, 0x66, 0x5F, 0x73, 0x74, 0x64, 0x20, 0x1F, 0x66, 0x6E, 0x5B, 0x74, 0x2F, 0xFB, 0x6D, 0x2F, 0x1B, 0x3B, 0xE4, 0x0D, 0x35, 0x11, 0x2F, 0xFC, 0x56, 0x90, 0x2F, 0xFF, 0xC4, 0x2F, 0xFB, 0xF8, 0x3E, 0x1F, 0x2F, 0xEC, 0x60, 0xAD, 0x2F, 0xF0, 0x94, 0x2F, 0xF4, 0xC8, 0x2F, 0xF8, 0x32, 0xA7, 0x30, 0x2F, 0x50, 0x56, 0x64, 0x2F, 0x54, 0x98, 0x2F, 0x58, 0xCC, 0x2F, 0x5C, 0x4D, 0xCF, 0x4C, 0x11, 0x6F, 0x67, 0x6F, 0xAF, 0x39, 0xFF, 0xFF, 0xFF, 0x30, 0x03, 0xBE, 0x00, 0x40, 0x02, 0x15, 0x5A, 0xF8, 0x30, 0xB2, 0xAF, 0xC2, 0x3E, 0x57, 0x5E, 0x5B, 0x54, 0x0E, 0x69, 0x74, 0x6C, 0x65, 0x00, 0x2F, 0xDC, 0x00, 0x70, 0x4F, 0x3F, 0xFF, 0x48, 0x08, 0x65, 0x61, 0x74, 0x68, 0x01, 0xE0, 0x33, 0x50, 0x75, 0x62, 0x02, 0x6C, 0x69, 0x73, 0x68, 0x65, 0x72, 0x01, 0xA0, 0x67, 0x49, 0x18, 0x53, 0x42, 0x4E, 0x00, 0x31, 0xBB, 0x00, 0xF0, 0x33, 0x5F, 0x4E, 0x75, 0xC0, 0x31, 0x8A, 0x01, 0x80, 0xCF, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x61, 0x78, 0x63, 0x31, 0x9E, 0x02, 0x00, 0x33, 0xF0, 0x6B, 0x00, 0xB1, 0x37, 0x4E, 0x65, 0x77, 0x66, 0x73, 0x21, 0x07, 0x01, 0xC1, 0x6B, 0x4C, 0x53, 0x9A, 0x3E, 0x01, 0xE0, 0x67, 0x5F, 0x6A, 0x4C, 0xE1, 0x08, 0x00, 0xB1, 0xD3, 0x52, 0x02, 0xA0, 0x67, 0x52, 0x01, 0xA0, 0x67, 0x70, 0x10, 0x61, 0x6E, 0x31, 0x3E, 0x0F, 0x01, 0x04, 0xFF, 0x00, 0x01, 0x52, 0x6F, 0x6F, 0x74, 0x50, 0x61, 0x6E, 0x00, 0x32, 0x7E, 0xE1, 0x00, 0x63, 0xB2, 0x72, 0xB7, 0x53, 0x93, 0x70, 0x61, 0x73, 0x31, 0x3E, 0x63, 0xA7, 0x70, 0x53, 0x03, 0x20, 0x53, 0x4E, 0x5F, 0x30, 0x55, 0x00, 0x05, 0xF6, 0x01, 0x20, 0x53, 0xA1, 0x4F, 0x93, 0x42, 0x80, 0x53, 0x69, 0x63, 0x31, 0x80, 0x3E, 0x56, 0x3F, 0x07, 0xFF, 0x00, 0x43, 0x73, 0x73, 0x48, 0x2F, 0xD7, 0x84, 0xDF, 0x00, 0x23, 0x5F, 0x2F, 0xB3, 0x3C, 0x80, 0x42, 0x00, 0x13, 0x43, 0x54, 0x59, 0x93, 0x8B, 0xF3, 0x97, 0x80, 0x3F, 0xBE, 0x71, 0x27, 0x07, 0x40, 0xD3, 0x00, 0x73, 0x09, 0x30, 0x7F, 0x40, 0x03, 0x00, 0x61, 0x27, 0x96, 0xA0, 0x2F, 0xA7, 0xC8, 0x80, 0xD3, 0x74, 0x78, 0x74, 0x31, 0x84, 0xEC, 0x61, 0x7B, 0x00, 0x73, 0xF7, 0x5F, 0xEE, 0xC4, 0x00, 0x22, 0x74, 0x54, 0x33, 0xCE, 0xCC, 0x41, 0xF4, 0x2F, 0xFF, 0xCC, 0x41, 0x0E, 0x00, 0x0E, 0x85, 0x0B, 0xD4, 0x34, 0xD7, 0x94, 0x1F, 0xAA, 0x2F, 0xB7, 0xCC, 0x8F, 0xBB, 0x65, 0x50, 0x00, 0xB7, 0x5E, 0x38, 0x6E, 0x0F, 0x62, 0xE0, 0x5F, 0x3F, 0x4A, 0x54, 0x3F, 0xF6, 0x30, 0x83, 0x37, 0x63, 0x31, 0xFF, 0x00, 0x74, 0x47, 0x5F, 0xF7, 0x44, 0x38, 0x00, 0x80, 0x83, 0x67, 0x66, 0x68, 0x27, 0xDE, 0x9C, 0x42, 0x1A, 0x88, 0x00, 0x88, 0x4F, 0xF3, 0x00, 0x10, 0x83, 0x8C, 0x2F, 0xAB, 0xA8, 0x80, 0x7F, 0xAF, 0xC0, 0xB5, 0x62, 0x36, 0x52, 0x0D, 0x4E, 0x2C, 0x6F, 0x82, 0x30, 0x87, 0x20, 0x25, 0xE1, 0x30, 0x03, 0xD2, 0x62, 0x02, 0xDD, 0x7E, 0xD7, 0x76, 0x48, 0x72, 0x30, 0x9B, 0x0A, 0x00, 0x00, 0xE8, 0x6C, 0x0F, 0x61, 0xEA, 0x81, 0x11, 0x08, 0x62, 0xDD, 0x4F, 0xA4, 0x80, 0x21, 0x28, 0x8C, 0x32, 0x00, 0x96, 0xD7, 0x53, 0x97, 0x9A, 0x0A, 0x4E, 0x53, 0x02, 0x5F, 0x0A, 0x00, 0x02, 0x90, 0xA6, 0x40, 0xC7, 0xCA, 0x10, 0x76, 0x11, 0x81, 0x70, 0x43, 0x89, 0x6C, 0xF7, 0x8F, 0x80, 0x30, 0xDB, 0x24, 0x4F, 0xAB, 0x8E, 0x0A, 0x00, 0x08, 0x00, 0x54, 0x06, 0x74, 0x89, 0x5B, 0x92, 0x63, 0xF6, 0x10, 0x65, 0xF4, 0x95, 0x70, 0x65, 0xAB, 0x4E, 0xD7, 0x53, 0x8F, 0x31, 0x01, 0x1F, 0x75, 0x3B, 0x26, 0x1C, 0x31, 0x7F, 0x3F, 0x9F, 0x32, 0xFB, 0xD8, 0x00, 0x75, 0x0F, 0x52, 0x53, 0xA0, 0x00, 0x09, 0x07, 0x75, 0xB3, 0x02, 0x00, 0x7C, 0x9C, 0x28, 0xDA, 0xA8, 0x41, 0x30, 0xC7, 0x26, 0x46, 0x00, 0xF0, 0xFB, 0x00, 0x5F, 0x00, 0x6C, 0xCF, 0x82, 0xE4, 0x51, 0xF0, 0x51, 0x35, 0x00, 0x75, 0x50, 0x5B, 0xF3, 0x97, 0xCF, 0x50, 0xFA, 0x00, 0x51, 0x48, 0x72, 0x3E, 0x79, 0x09, 0x67, 0x50, 0x06, 0x96, 0x6C, 0x51, 0xF8, 0x53, 0x52, 0x13, 0x32, 0xE7, 0x01, 0x22, 0x00, 0xFF, 0x00, 0x85, 0x6F, 0x00, 0x00, 0xBE, 0x2F, 0xEB, 0x70, 0xD0, 0x00, 0x27, 0x47, 0x76, 0x47, 0x14, 0x2E, 0xE3, 0x9C, 0x41, 0x0A, 0x00, 0x75, 0x0A, 0x47, 0x1B, 0x41, 0xE7, 0xC2, 0x13, 0x82, 0x2F, 0xD7, 0x9C, 0x8F, 0xDB, 0x03, 0x49, 0x00, 0x53, 0x00, 0x42, 0x00, 0x55, 0xDA, 0x32, 0x93, 0x62, 0x98, 0xA0, 0x7F, 0x00, 0x35, 0xBB, 0x00, 0x00, 0x58, 0x00, 0xE0, 0x7F, 0x34, 0x81, 0x32, 0x0F, 0x41, 0x24, 0x00, 0x24, 0x00, 0x05, 0x01, 0x20, 0x7F, 0x5F, 0x30, 0x40, 0x01, 0x2D, 0x60, 0x03, 0x70, 0x01, 0x70, 0x0B, 0x30, 0x17, 0xA3, 0x2B, 0xC5, 0x21, 0x17, 0x00, 0x76, 0x1F, 0x00, 0x00, 0xC2, 0x29, 0x9B, 0x04, 0x00, 0xA3, 0xFF, 0x68, 0xBE, 0x41, 0x17, 0x33, 0x2B, 0x06, 0x01, 0x21, 0x17, 0x08, 0x54, 0x0C, 0x00, 0x54, 0x7B, 0x76, 0xB0, 0x8B, 0xF7, 0x53, 0x1A, 0xFB, 0x47, 0x67, 0x33, 0xAF, 0x38, 0x1F, 0xB0, 0x83, 0x00, 0x16, 0xDB, 0xE0, 0x2F, 0x83, 0x00, 0xB0, 0x83, 0x47, 0x0C, 0x41, 0x1B, 0x1A, 0x00, 0x1A, 0x2A, 0xED, 0x01, 0xB1, 0x1B, 0xD1, 0x15, 0xF5, 0x73, 0xBB, 0x72, 0x2B, 0x00, 0x76, 0xCB, 0x51, 0x13, 0x4C, 0x00, 0xA5, 0x13, 0x80, 0x82, 0x2B, 0xC0, 0x3F, 0xF3, 0x00, 0xF2, 0x2B, 0xB0, 0x65, 0xFA, 0x51, 0xA1, 0x5B, 0x2F, 0x57, 0x5B, 0x74, 0x3B, 0x78, 0x62, 0xAB, 0x00, 0x77, 0x17, 0x21, 0x0F, 0x2F, 0xCF, 0x6B, 0x4A, 0x00, 0xB5, 0x93, 0x42, 0x8B, 0x04, 0x29, 0xC5, 0x09, 0x01, 0x22, 0xAB, 0x30, 0x78, 0xFE, 0x00, 0x20, 0xF7, 0x00, 0x07, 0x5B, 0x20, 0xA9, 0x2F, 0xB7, 0x00, 0xB0, 0xF7, 0x36, 0x5F, 0x53, 0x23, 0x0A, 0xFE, 0x01, 0x82, 0xA3, 0x91, 0x77, 0x70, 0xF7, 0x00, 0x77, 0xA7, 0x2A, 0xB5, 0x2C, 0x67, 0x01, 0x50, 0xF7, 0x0B, 0xBE, 0x01, 0x23, 0xA3, 0x5D, 0x00, 0x60, 0xF7, 0xF7, 0xEB, 0x21, 0xA1, 0x2C, 0xDF, 0x00, 0xB1, 0xEF, 0xA0, 0xBA, 0x44, 0x1B, 0x0C, 0x2F, 0xE5, 0x7F, 0xE7, 0x01, 0x30, 0xF7, 0xF7, 0x24, 0x9B, 0x70, 0x30, 0x61, 0x65, 0x67, 0xDF, 0xD0, 0x07, 0x67, 0x72, 0x70, 0x31, 0xC3, 0x3F, 0x6F, 0x38, 0x3F, 0x47, 0x72, 0x6F, 0x75, 0x3F, 0x67, 0x7F, 0xFA, 0x38, 0x67, 0x72, 0x58, 0x13, 0x30, 0x23, 0x3F, 0x83, 0x47, 0x5F, 0x41, 0xFE, 0xCE, 0x03, 0x35, 0x33, 0xF8, 0x23, 0xFB, 0x53, 0xF7, 0x6F, 0x30, 0x6F, 0x3E, 0x6F, 0x47, 0x3B, 0x5F, 0x42, 0xCE, 0x4F, 0x3F, 0xC3, 0x01, 0x30, 0x3B, 0x2C, 0x00, 0x2E, 0x8B, 0x3E, 0xAB, 0x98, 0xF8, 0xAB, 0x67, 0x72, 0x50, 0xEF, 0x00, 0x7C, 0x9F, 0x3C, 0x10, 0x00, 0x2F, 0x00, 0x22, 0x00, 0x0C, 0x9F, 0xC8, 0x8C, 0x9F, 0x36, 0x5B, 0x33, 0xE3, 0x3F, 0x13, 0x57, 0x2D, 0x2F, 0xFC, 0x3E, 0x2F, 0xFF, 0x4F, 0x3E, 0x81, 0x3C, 0xD3, 0x2F, 0xFF, 0x8E, 0x33, 0x3B, 0x33, 0x64, 0x73, 0x6C, 0x3D, 0x6C, 0xB2, 0x80, 0x10, 0x31, 0xA9, 0xF0, 0x10, 0x32, 0xF0, 0x21, 0x33, 0x6C, 0xE5, 0x4C, 0x54, 0x90, 0x3E, 0xC0, 0x30, 0x0B, 0x70, 0x39, 0x4C, 0x54, 0x4D, 0x61, 0x73, 0x6B, 0xDA, 0x90, 0x5A, 0x3C, 0xEB, 0xA8, 0x24, 0xF8, 0x32, 0x6F, 0x38, 0x2F, 0xFC, 0x88, 0xD5, 0x34, 0xE3, 0x2F, 0xA4, 0x88, 0x2F, 0xA8, 0x08, 0x2F, 0xCB, 0x88, 0x2F, 0xCF, 0x55, 0x4C, 0x2D, 0x0B, 0xE8, 0x2D, 0x0F, 0xAC, 0x2D, 0x54, 0x48, 0x25, 0xBC, 0x6D, 0x0C, 0x25, 0x28, 0x00, 0x3F, 0x27, 0xAA, 0x00, 0xAC, 0x93, 0x3C, 0xE3, 0x02, 0x00, 0xAC, 0xE3, 0xDB, 0x00, 0x3F, 0x37, 0x00, 0xBD, 0x33, 0xD5, 0x45, 0xAC, 0x00, 0x9D, 0x33, 0x40, 0x2E, 0x00, 0x30, 0x03, 0x46, 0x11, 0x39, 0x53, 0x06, 0x00, 0x04, 0x30, 0x03, 0x30, 0x0B, 0x65, 0x1C, 0x06, 0x00, 0x01, 0x30, 0x03, 0x30, 0x17, 0x75, 0x6B, 0x01, 0x04, 0x4D, 0x05, 0x2F, 0xF7, 0x4F, 0x5F, 0x31, 0x32, 0x01, 0xB0, 0x7F, 0x01, 0x03, 0xE0, 0x7F, 0xC9, 0xD2, 0xB9, 0x29, 0x21, 0x8C, 0x8C, 0x05, 0xA0, 0x7F, 0x44, 0x73, 0xFB, 0x91, 0xA3, 0x00, 0xF1, 0x7F, 0x03, 0x03, 0xC1, 0x7F, 0x52, 0x65, 0x64, 0x00, 0x2C, 0x12, 0x2E, 0xCC, 0x4E, 0x40, 0x00, 0x2F, 0x37, 0x80, 0x3F, 0x27, 0x28, 0x26, 0x1F, 0x2F, 0x34, 0x04, 0x00, 0x04, 0x06, 0x00, 0x06, 0x06, 0x73, 0x09, 0xED, 0x61, 0xBE, 0x30, 0x03, 0x3F, 0x6F, 0x3A, 0x57, 0xDE, 0x40, 0x30, 0x03, 0xB8, 0xE0, 0x13, 0xC0, 0x30, 0x03, 0x00, 0x7F, 0x63, 0x73, 0xF0, 0x10, 0x04, 0x00, 0x05, 0x01, 0x10, 0x04, 0x10, 0x02, 0xA2, 0x37, 0x46, 0xF2, 0x37, 0x06, 0x26, 0x06, 0x02, 0x05, 0x66, 0x28, 0x2C, 0x00, 0x12, 0x43, 0x42, 0x65, 0x6C, 0x33, 0x5A, 0x01, 0x6F, 0xAA, 0x80, 0xEA, 0x28, 0x70, 0x05, 0x2F, 0xF7, 0x87, 0x30, 0x03, 0x30, 0x8E, 0xE3, 0xBE, 0x30, 0x03, 0xB0, 0xBF, 0xE0, 0x13, 0xDA, 0xC0, 0xBF, 0x50, 0xA7, 0x00, 0x00, 0xC0, 0xA7, 0x00, 0x21, 0x5F, 0x31, 0x02, 0x71, 0x5F, 0x2F, 0x18, 0xA1, 0xBD, 0xBF, 0x30, 0x03, 0x3F, 0xF3, 0xCE, 0x95, 0x17, 0x6F, 0x41, 0x30, 0x03, 0xE0, 0x13, 0xC1, 0x30, 0x03, 0x05, 0x21, 0x5F, 0x00, 0x00, 0xC3, 0x01, 0x31, 0x5F, 0x0F, 0x61, 0x0B, 0xB6, 0xBF, 0x30, 0x03, 0xB0, 0xBF, 0xE0, 0x13, 0xC0, 0xBF, 0xBF, 0x02, 0x61, 0x5F, 0x32, 0x02, 0x72, 0xBF, 0x2E, 0xDB, 0x2C, 0x4F, 0x30, 0x03, 0x44, 0xBD, 0x2D, 0x9F, 0xFE, 0x30, 0x03, 0xC0, 0x13, 0x2B, 0xDB, 0x30, 0x03, 0x05, 0x02, 0xBF, 0x00, 0x00, 0xC3, 0x01, 0x32, 0xBF, 0x9A, 0x1F, 0x99, 0x19, 0xC0, 0x30, 0x03, 0xB0, 0xBF, 0xE0, 0x13, 0xC0, 0xBF, 0x01, 0xF2, 0xBF, 0xE3, 0x7F, 0x6B, 0x3F, 0x17, 0x38, 0x53, 0x50, 0x61, 0x6E, 0x00, 0x9F, 0x1A, 0x00, 0x8F, 0xEB, 0xEB, 0x57, 0x87, 0x7F, 0x6B, 0x7F, 0xBF, 0x03, 0x4F, 0xBF, 0x57, 0x00, 0x53, 0xB9, 0x01, 0x0F, 0xBF, 0xE1, 0x2D, 0x26, 0x20, 0x03, 0x80, 0x53, 0x69, 0x63, 0x31, 0xA0, 0x4F, 0xBF, 0x63, 0xF5, 0x00, 0x84, 0xD3, 0x70, 0x53, 0x46, 0x31, 0x32, 0x00, 0x63, 0x2F, 0x58, 0x2F, 0xA0, 0xF7, 0x4B, 0x05, 0x4F, 0x49, 0x00, 0x00, 0xCD, 0xCC, 0x4C, 0x9F, 0x28, 0x36, 0x80, 0x3F, 0x50, 0x07, 0x40, 0x0F, 0x4F, 0xF7, 0x50, 0x07, 0x8F, 0xAC, 0x7F, 0x40, 0xE0, 0x0B, 0x40, 0x03, 0xB0, 0xA7, 0x4E, 0x53, 0x3E, 0xE7, 0x00, 0x94, 0xB7, 0x60, 0xFB, 0x7D, 0x20, 0x01, 0xC0, 0xA7, 0x27, 0x62, 0x01, 0x00, 0xA7, 0x8A, 0x37, 0x81, 0x2F, 0x91, 0x00, 0x84, 0xA3, 0x8B, 0x71, 0x83, 0x10, 0xF4, 0xBF, 0x01, 0xC1, 0x2F, 0x07, 0x04, 0xD1, 0x2F, 0x00, 0x80, 0xA7, 0xBF, 0x01, 0xF1, 0x2F, 0x08, 0x02, 0x41, 0x2F, 0x3B, 0x13, 0x00, 0x54, 0x73, 0xA1, 0xB7, 0xEE, 0xF7, 0x00, 0xD2, 0x5F, 0x77, 0x09, 0x04, 0xD2, 0x5F, 0x00, 0xB0, 0xA7, 0x01, 0xC3, 0x07, 0x0A, 0x01, 0xE2, 0x5F, 0x92, 0xE7, 0x00, 0x1A, 0xB3, 0xAE, 0xD3, 0xE7, 0xA0, 0x00, 0x68, 0x1F, 0x10, 0x43, 0xE3, 0xFA, 0xDB, 0x5C, 0x21, 0x50, 0x8F, 0x43, 0x83, 0x00, 0x00, 0x44, 0x68, 0x47, 0x30, 0x0F, 0x3F, 0xD7, 0x30, 0x0F, 0x27, 0x80, 0x3F, 0x73, 0x67, 0x03, 0x05, 0x33, 0x67, 0x00, 0x1A, 0xE3, 0x5F, 0xEE, 0x7B, 0xF8, 0x37, 0x37, 0x00, 0xA0, 0x7F, 0x3F, 0x8F, 0x00, 0x10, 0x7F, 0x01, 0x6C, 0x5D, 0x9F, 0xBB, 0xEE, 0x00, 0x0F, 0xC7, 0x23, 0x67, 0xE3, 0xEF, 0x07, 0x33, 0xEF, 0x00, 0x1A, 0xEB, 0x01, 0x94, 0xEB, 0x80, 0x5B, 0x41, 0xFB, 0xE3, 0x02, 0x01, 0x30, 0x87, 0x74, 0x6F, 0x01, 0x50, 0x7F, 0xFA, 0xEB, 0xBD, 0x02, 0xB0, 0x7F, 0x03, 0x81, 0x07, 0x90, 0xF7, 0xF1, 0x17, 0x00, 0x02, 0x0F, 0x03, 0x34, 0xF7, 0xDF, 0x00, 0x1A, 0xF3, 0x01, 0x51, 0x8F, 0x00, 0x2D, 0xCF, 0x00, 0x12, 0x0F, 0x2A, 0x3A, 0x01, 0x21, 0x8F, 0x02, 0x5F, 0x27, 0x7F, 0xDC, 0x00, 0x2F, 0x27, 0x3F, 0xAB, 0xF6, 0xB7, 0xFD, 0x97, 0xFD, 0x57, 0xFC, 0xE7, 0xFC, 0x77, 0xFF, 0xFC, 0x07, 0xFB, 0x97, 0xFA, 0xE3, 0xFA, 0x57, 0xF9, 0xA3, 0xF9, 0x17, 0xF8, 0x63, 0x3F, 0xB7, 0x75, 0xCC, 0x00, 0x2F, 0xB7, 0x3E, 0x8F, 0x0A, 0x30, 0xCB, 0x2C, 0x41, 0xA7, 0x43, 0xCF, 0x1B, 0xCC, 0x37, 0x0D, 0xF8, 0x5F, 0x67, 0x72, 0x56, 0xFF, 0x08, 0x40, 0x02, 0x60, 0x00, 0x1E, 0x5A, 0xF8, 0xFA, 0x34, 0xDF, 0x2C, 0x9F, 0x4F, 0x67, 0x00, 0x0C, 0xD1, 0x82, 0x00, 0xA0, 0xFC, 0xFF, 0x5F, 0x00, 0xFE, 0x00, 0xFF, 0x60, 0x5A, 0x48, 0xFE, 0xED, 0xB5, 0xDF, 0x00, 0x28, 0xF9, 0x20, 0x26, 0xFF, 0xFE, 0x3F, 0xEB, 0x1A, 0xEF, 0x68, 0xB4, 0x08, 0x40, 0xEB, 0x20, 0x42, 0x50, 0x3F, 0xFF, 0xF6, 0x40, 0xFF, 0x26, 0x2F, 0xF7, 0x63, 0x00, 0x03, 0x00, 0xC0, 0xF4, 0x00, 0x10, 0xFD, 0xFF, 0x40, 0xE8, 0x2F, 0xF8, 0xF5, 0xF0, 0xFF, 0xFF, 0x20, 0x50, 0x09, 0xFF, 0xFF, 0x30, 0x20, 0x58, 0x49, 0x9F, 0x6F, 0x9F, 0xE9, 0x02, 0x4F, 0x4F, 0x00, 0x00, 0x6F, 0xAF, 0xBF, 0xF9, 0xF2, 0x43, 0x60, 0x5F, 0x2F, 0x0E, 0x8F, 0xFF, 0xF9, 0x51, 0x37, 0x3F, 0xDA, 0x06, 0xF5, 0xF2, 0xFF, 0xFF, 0xF2, 0x20, 0x03, 0x4F, 0xE6, 0x26, 0x32, 0x00, 0x22, 0x4F, 0xEE, 0x29, 0xC2, 0xFF, 0x58, 0x29, 0x23, 0x06, 0x03, 0xFF, 0xFF, 0x2F, 0x2F, 0x00, 0x00, 0x30, 0x03, 0x4F, 0xF3, 0x50, 0x22, 0xA0, 0x1F, 0xC1, 0x50, 0x77, 0x0A, 0x0A, 0x00, 0x30, 0x0A, 0x0A, 0x0A, 0xD0, 0xF3, 0x6F, 0xE3, 0x64, 0x4F, 0xEB, 0x46, 0x10, 0x00, 0x00, 0xE3, 0x24, 0x6A, 0x8F, 0x9F, 0x00, 0x66, 0x03, 0xFF, 0xF4, 0x2D, 0xDF, 0xC0, 0xC6, 0x90, 0x6F, 0xBF, 0xBC, 0x63, 0x04, 0x01, 0x52, 0x5C, 0x20, 0xB7, 0x20, 0x00, 0xF0, 0x20, 0xEB, 0x30, 0x03, 0xB0, 0x2F, 0xF1, 0xF8, 0x30, 0xCB, 0x20, 0xB6, 0xFF, 0x66, 0x00, 0x66, 0x38, 0x00, 0x02, 0x20, 0xE3, 0x20, 0x6E, 0x2E, 0xBC, 0x00, 0x04, 0xFF, 0x10, 0xFF, 0x0D, 0x8F, 0x7F, 0xEB, 0xF7, 0x30, 0xFF, 0xFD, 0x00, 0x00, 0x00, 0x30, 0x00, 0x19, 0xFF, 0x00, 0xAA, 0x60, 0xE6, 0x61, 0xE7, 0x2F, 0x39, 0xC0, 0xF5, 0xF9, 0xFF, 0xDF, 0x80, 0x20, 0xD5, 0x07, 0x10, 0xFC, 0xFC, 0xAF, 0xDF, 0xFF, 0x10, 0x02, 0x9F, 0x6F, 0x3A, 0xAE, 0x35, 0x00, 0xD7, 0x02, 0x8C, 0x30, 0x41, 0x00, 0xFF, 0xFD, 0x40, 0xEF, 0x21, 0x3B, 0x00, 0x00, 0x00, 0xF9, 0xF2, 0x01, 0x0B, 0x20, 0x00, 0xCF, 0xFF, 0x01, 0x21, 0xFF, 0xA8, 0x00, 0x5A, 0x00, 0x20, 0x21, 0x63, 0x40, 0x20, 0x2F, 0xE5, 0x0B, 0x0A, 0xF6, 0xF6, 0x0A, 0x0C, 0x00, 0xF6, 0xF2, 0xF7, 0x8E, 0xFF, 0xFF, 0x21, 0x00, 0x01, 0x69, 0x00, 0x8F, 0xFF, 0xA2, 0x06, 0x12, 0x3F, 0x3C, 0x00, 0x4F, 0xFF, 0x00, 0xDF, 0xFF, 0x00, 0x1C, 0xFF, 0x80, 0x3E, 0xAD, 0x00, 0x00, 0xC3, 0xFF, 0xFC, 0xFF, 0xFF, 0x00, 0x40, 0x00, 0xA9, 0x00, 0xFB, 0xFF, 0xFF, 0x4F, 0x55, 0x6A, 0x2F, 0xB4, 0x0A, 0x3F, 0xBA, 0x09, 0x9F, 0xD9, 0x03, 0x04, 0x83, 0x57, 0xC0, 0xE8, 0x1E, 0x7F, 0xDC, 0xF6, 0xFF, 0xFF, 0x10, 0x00, 0xC6, 0x8E, 0x3F, 0xE4, 0x6F, 0xFF, 0x00, 0xA0, 0x88, 0x05, 0x00, 0x8F, 0x01, 0x5D, 0x01, 0x43, 0x02, 0x4C, 0x49, 0x4D, 0xFF, 0xFE, 0x14, 0x32, 0x7C, 0x02, 0x60, 0x28, 0x2A, 0x37, 0x3B, 0x9D, 0x69, 0x6D, 0x61, 0x67, 0x10, 0x8C, 0x4C, 0x24, 0x20, 0x00, 0x0D, 0x42, 0x30, 0x07, 0x03, 0x8B, 0xA0, 0x00, 0x02, 0x71, 0x00, 0x88, 0xFE, 0xFF, 0xFF, 0x26, 0x0E, 0xC0, 0x80, 0x2F, 0x0B, 0xC0, 0xC0, 0xAF, 0x9F, 0x00, 0x00, 0x9F, 0x81, 0x20, 0x03, 0x00, 0x88, 0x00, 0x88, 0xFF, 0xCC, 0x20, 0x17, 0xC0, 0x70, 0x07, 0xFF, 0xFF, 0x78, 0x00, 0x02, 0xFF, 0xFC, 0x3E, 0xC3, 0x4F, 0xDB, 0x3F, 0xDF, 0x90, 0x90, 0xDF, 0xDF, 0x30, 0x03, 0x01, 0xA1, 0xD7, 0xE4, 0x40, 0x6F, 0x30, 0x6B, 0x40, 0x6F, 0x00, 0xB0, 0x43, 0xCF, 0xDF, 0xFF, 0x05, 0x55, 0xFF, 0xD7, 0x00, 0xEE, 0x00, 0x0F, 0x0E, 0x55, 0x20, 0x17, 0x74, 0xEE, 0x20, 0x17, 0x70, 0x07, 0x40, 0x6F, 0x80, 0x90, 0x6F, 0xC5, 0xFF, 0x0F, 0xCF, 0x7F, 0xDE, 0x00, 0x95, 0xDD, 0xC1, 0x7F, 0x2F, 0xA3, 0xB1, 0x7F, 0x1D, 0x20, 0x00, 0x10, 0x51, 0x7F, 0xB9, 0xCA, 0x06, 0xC6, 0x17, 0x50, 0xA8, 0x82, 0x61, 0x70, 0x28, 0x8E, 0x2E, 0x46, 0x10, 0x00, 0x43, 0xFD, 0x3A, 0xEF, 0x12, 0x76, 0x00, 0x98, 0x6F, 0xFF, 0xCE, 0x47, 0x2D, 0xE3, 0xFF, 0x11, 0x7A, 0xFF, 0x45, 0x4F, 0xEF, 0xAA, 0x00, 0xBB, 0x4B, 0x0F, 0x45, 0xBB, 0x50, 0x07, 0xFF, 0x23, 0xEF, 0x3F, 0xD6, 0x00, 0x23, 0xDE, 0x45, 0x53, 0x4F, 0xFB, 0x9A, 0x00, 0x68, 0x4B, 0x2F, 0x24, 0x35, 0x23, 0x0A, 0xAD, 0xFF, 0xFF, 0xC8, 0x3B, 0x3B, 0xB3, 0x33, 0x2F, 0xFF, 0x43, 0xFF, 0x66, 0x67, 0x27, 0xFF, 0x00, 0x4B, 0x83, 0x4F, 0x7B, 0xE7, 0xF0, 0x21, 0xD1, 0x2E, 0x4D, 0x38, 0x0A, 0x08, 0x47, 0x29, 0x21, 0xF6, 0x22, 0xFF, 0x22, 0xF7, 0xF7, 0x00, 0x15, 0x7F, 0x22, 0xFF, 0x32, 0x4F, 0xBA, 0x43, 0x30, 0xFF, 0x97, 0x6C, 0x27, 0x36, 0x6A, 0x10, 0xE7, 0xF2, 0xF4, 0x7C, 0xFF, 0x34, 0xBA, 0x40, 0x03, 0x9F, 0xDB, 0x25, 0x32, 0x8F, 0xE8, 0x0C, 0x09, 0x20, 0xFF, 0x4F, 0x25, 0x2D, 0xAD, 0xBF, 0x04, 0x28, 0xFF, 0x31, 0x00, 0x6C, 0x06, 0xF4, 0x37, 0xFF, 0x87, 0xD6, 0x00, 0xDD, 0x00, 0x4D, 0x3C, 0x1A, 0xDD, 0x00, 0xEE, 0x34, 0x4A, 0x31, 0xEF, 0x54, 0x00, 0x45, 0x1F, 0xB8, 0xA4, 0x38, 0x0B, 0x51, 0x41, 0xEF, 0xFD, 0xA0, 0x97, 0x1F, 0x10, 0x00, 0x0C, 0xFE, 0xFC, 0x10, 0xA0, 0x23, 0xF1, 0x6F, 0xB8, 0x2C, 0xEF, 0x02, 0x00, 0x03, 0xFF, 0xFF, 0x1E, 0x8F, 0xA1, 0x1B, 0xEF, 0xE7, 0x21, 0x1F, 0xC7, 0x69, 0x04, 0xD9, 0x32, 0xA1, 0xF2, 0x27, 0xCB, 0x20, 0x03, 0x7F, 0xD9, 0x42, 0xE1, 0x40, 0xD7, 0x37, 0xFF, 0x01, 0xBE, 0x4D, 0xEF, 0x58, 0x22, 0x00, 0x23, 0x4F, 0xBB, 0x64, 0xFF, 0xA7, 0x47, 0xEF, 0xDC, 0x2C, 0xFF, 0xED, 0x79, 0xE0, 0xDE, 0x24, 0xA0, 0x37, 0x04, 0xCC, 0xFF, 0x88, 0x50, 0xCF, 0x21, 0x00, 0x32, 0x42, 0xDF, 0x33, 0x00, 0x33, 0x09, 0x00, 0x00, 0x73, 0x30, 0x26, 0xAA, 0xFF, 0xFF, 0x40, 0x04, 0xCE, 0x63, 0x3F, 0x46, 0xD7, 0x7A, 0xEF, 0x35, 0x94, 0x72, 0xEF, 0x26, 0xF5, 0x2F, 0x2E, 0x05, 0x4D, 0x2E, 0xDA, 0x6B, 0x03, 0xE4, 0x0C, 0x09, 0x55, 0xFF, 0x08, 0xC0, 0x7F, 0x91, 0x00, 0x00, 0x00, 0xF3, 0xF3, 0x00, 0x99, 0x00, 0x99, 0xFE, 0x5F, 0xF7, 0x20, 0x0B, 0x20, 0x0F, 0x7F, 0x8F, 0x80, 0x17, 0x60, 0x1F, 0x8F, 0xA7, 0x56, 0x1A, 0xFF, 0x55, 0x01, 0x3A, 0xFD, 0x90, 0x1F, 0x78, 0x4F, 0xC3, 0x55, 0x23, 0xFF, 0x65, 0x4A, 0x2F, 0x97, 0xFF, 0xFC, 0x35, 0x5C, 0x29, 0x23, 0x63, 0x02, 0x34, 0x07, 0x3F, 0xFB, 0x8B, 0xFF, 0x03, 0x44, 0x10, 0x28, 0x4D, 0x68, 0xD4, 0x80, 0x5F, 0x3F, 0xE5, 0x17, 0x9F, 0xEA, 0xEF, 0xFF, 0x07, 0x68, 0xCF, 0x45, 0x6F, 0x2B, 0x59, 0x3E, 0xFB, 0x5F, 0x30, 0x20, 0xFB, 0x89, 0x5F, 0xC7, 0xF3, 0xF9, 0xF8, 0x90, 0x3F, 0x31, 0xB7, 0x22, 0x97, 0x30, 0x00, 0x75, 0x85, 0xBF, 0x2F, 0xC2, 0xAF, 0x0D, 0xFF, 0x9E, 0x22, 0xFF, 0x45, 0x4F, 0xB9, 0xA9, 0x00, 0x9A, 0x45, 0xBF, 0x89, 0x88, 0x55, 0xA7, 0xFF, 0x22, 0xFF, 0x3E, 0xDF, 0x00, 0xFF, 0x75, 0x29, 0xFF, 0xDA, 0x4F, 0xFF, 0x23, 0x3A, 0xDB, 0x5E, 0x7F, 0x95, 0x9F, 0x1F, 0x7F, 0x8F, 0x52, 0x23, 0x0C, 0x0D, 0x92, 0x31, 0xE1, 0xEF, 0xE1, 0xFF, 0x7F, 0xFF, 0x7C, 0x02, 0x2C, 0xE9, 0x30, 0x03, 0xF0, 0x0F, 0x01, 0x1D, 0xE6, 0x45, 0x3E, 0x00, 0xFB, 0x5B, 0xB0, 0x3A, 0x47, 0xFE, 0x2B, 0x83, 0x8C, 0x57, 0xD0, 0x28, 0x8B, 0x25, 0x31, 0xB0, 0x77, 0x11, 0x0D, 0xA5, 0x1B, 0x96, 0x44, 0x00, 0x00, 0xFC, 0xFB, 0x18, 0x01, 0x07, 0xF8, 0x3B, 0xB6, 0x56, 0x45, 0x0E, 0x50, 0x00, 0x28, 0x2F, 0x3F, 0x2C, 0x8F, 0xE5, 0x2C, 0xC3, 0x00, 0xFA, 0x30, 0xA1, 0x2B, 0xBB, 0x6F, 0x76, 0x87, 0x18, 0xEF, 0x00, 0x38, 0x77, 0x77, 0xC2, 0xC2, 0x5F, 0xAE, 0x8B, 0x6B, 0xFF, 0x01, 0xAF, 0x47, 0xCF, 0x15, 0xEE, 0x32, 0x6B, 0x26, 0x89, 0x00, 0x3E, 0xA7, 0x3A, 0x0D, 0xB4, 0x2F, 0x04, 0xF1, 0xFF, 0x7F, 0xFF, 0xA0, 0x50, 0xB0, 0x26, 0x73, 0xF4, 0x79, 0x7C, 0x00, 0x60, 0xFB, 0xFF, 0xE0, 0x28, 0x32, 0x00, 0xB0, 0x01, 0x24, 0x07, 0x4F, 0x08, 0x2F, 0x1F, 0x00, 0x39, 0x00, 0x0D, 0x3D, 0x04, 0x7D, 0xFB, 0xFE, 0xE5, 0x00, 0xD8, 0x5C, 0xA7, 0x5B, 0xA5, 0x3F, 0x93, 0x61, 0x00, 0x1C, 0xBF, 0x38, 0x93, 0x40, 0x96, 0x9E, 0x2A, 0x03, 0xA5, 0x4F, 0xF4, 0xFE, 0x28, 0xAF, 0xD0, 0xE1, 0x3E, 0xFF, 0x1A, 0x27, 0x87, 0x8C, 0x3E, 0x05, 0x00, 0x00, 0x3F, 0x2B, 0x55, 0x98, 0xBE, 0x04, 0x07, 0x0B, 0xFF, 0xFF, 0x08, 0x06, 0x0E, 0x53, 0xFF, 0x20, 0x4A, 0xBF, 0x3F, 0xB6, 0x8E, 0xB3, 0xFF, 0xDE, 0xFF, 0xDD, 0x55, 0x42, 0x60, 0x17, 0x7F, 0xD6, 0xDD, 0x01, 0xFF, 0xED, 0xFF, 0x00, 0x31, 0x00, 0x95, 0x7A, 0xDB, 0x92, 0x60, 0x37, 0xEE, 0x12, 0x2E, 0xBF, 0x50, 0xFD, 0xDA, 0x11, 0xFF, 0x12, 0xBD, 0xFF, 0x69, 0x45, 0xE7, 0x14, 0x6B, 0x9B, 0x0F, 0x8E, 0x1A, 0x5E, 0x01, 0x9F, 0x6F, 0xD3, 0x00, 0x1C, 0x2A, 0x35, 0x2F, 0x8F, 0xFC, 0x04, 0xFC, 0x00, 0xAD, 0x00, 0x47, 0x5A, 0x6F, 0xFD, 0x74, 0x8F, 0x4E, 0x97, 0xB9, 0xFF, 0xDC, 0x4F, 0xFF, 0x2F, 0x44, 0x2B, 0xB2, 0x4F, 0x3C, 0x35, 0xBB, 0xFF, 0x2B, 0xAA, 0x2D, 0x64, 0x10, 0x60, 0xB7, 0x32, 0x35, 0xDC, 0x0A, 0x10, 0x00, 0xB4, 0xEC, 0x2F, 0xF3, 0xF9, 0x7B, 0x78, 0xEF, 0x88, 0x68, 0x9F, 0x8B, 0xFF, 0x25, 0xAB, 0x8F, 0x6D, 0xFF, 0x8F, 0x5E, 0x02, 0x4E, 0xDD, 0x6C, 0x01, 0xEC, 0xAC, 0xCE, 0x7F, 0x2D, 0x16, 0xBE, 0x7F, 0x80, 0xE0, 0x7E, 0x7F, 0x9D, 0x2E, 0x04, 0x0F, 0xBD, 0xFF, 0xEF, 0xEF, 0x8A, 0xAF, 0x00, 0x8E, 0x47, 0x24, 0xDD, 0x78, 0xDD, 0x77, 0x33, 0x00, 0x11, 0x33, 0x11, 0x8D, 0x7D, 0x13, 0x13, 0x7D, 0xDF, 0x20, 0x03, 0x8A, 0xBF, 0x77, 0x50, 0x17, 0x70, 0x07, 0xFF, 0xFF, 0x30, 0x2B, 0xB0, 0x2F, 0xDB, 0xF0, 0x0F, 0x01, 0xBF, 0x7F, 0xA8, 0x6D, 0xEA, 0x7F, 0x7F, 0x10, 0x6D, 0xFF, 0x27, 0xB0, 0xD0, 0x04, 0xA1, 0x00, 0x0D, 0xB0, 0x01, 0x02, 0x60, 0xED, 0x61, 0xFF, 0x2C, 0xFF, 0x1A, 0xBE, 0xFF, 0xF0, 0x3E, 0xB7, 0x00, 0xC0, 0xFF, 0x19, 0x00, 0x21, 0x1D, 0x01, 0x8C, 0x28, 0xFA, 0xCC, 0xFF, 0x3A, 0x3B, 0x92, 0x40, 0x3F, 0x17, 0xFF, 0x46, 0x6B, 0x27, 0x4C, 0x84, 0xFF, 0xE9, 0xBD, 0xB9, 0x3C, 0xB8, 0xFD, 0xF1, 0x23, 0x34, 0x30, 0x62, 0x4C, 0xDA, 0x40, 0x13, 0xF7, 0xFF, 0xF1, 0x20, 0x03, 0x04, 0xEF, 0xFF, 0xE8, 0xFF, 0xE0, 0x20, 0x03, 0xE1, 0xFF, 0x1C, 0xD9, 0xFF, 0xD3, 0x50, 0x95, 0x2E, 0xE1, 0x21, 0x87, 0x57, 0xFF, 0x1A, 0x86, 0xFF, 0xD1, 0x93, 0x69, 0x30, 0x41, 0xFA, 0x31, 0x9F, 0xAC, 0x22, 0xFF, 0xC7, 0x41, 0xA5, 0xD9, 0xFF, 0xE4, 0x50, 0x5B, 0xF6, 0x20, 0xFF, 0xF2, 0x20, 0x5D, 0xFB, 0xFF, 0xEE, 0xFF, 0xEA, 0xAA, 0x2F, 0x23, 0xF5, 0x20, 0x05, 0xE4, 0x23, 0x97, 0xEA, 0x2E, 0x2E, 0xDA, 0x08, 0xFF, 0xDB, 0xFF, 0xD5, 0x2C, 0x6E, 0xC6, 0xFF, 0xD0, 0x02, 0xFF, 0xCB, 0xFF, 0xC1, 0xFF, 0xBC, 0x27, 0xE7, 0xE1, 0xA0, 0x20, 0x11, 0xD2, 0x24, 0x7A, 0xDA, 0xFF, 0xCD, 0xFF, 0xCA, 0x82, 0x20, 0x19, 0xC1, 0xFF, 0xB7, 0xFF, 0xB3, 0x20, 0xFE, 0xBA, 0x0A, 0xFF, 0xAF, 0xFF, 0xAB, 0x05, 0xD1, 0xFF, 0x5F, 0x62, 0x6D, 0x03, 0x28, 0xFF, 0x29, 0x20, 0xC2, 0xC2, 0xE1, 0x7F, 0x05, 0xFF, 0x9F, 0xAD, 0x22, 0x8D, 0x07, 0x21, 0x61, 0xA7, 0x20, 0x9A, 0x5F, 0xE9, 0x8A, 0xD9, 0x48, 0xA8, 0x38, 0x99, 0xFE, 0x41, 0x01, 0xF7, 0x25, 0x34, 0xEA, 0xFF, 0xE0, 0x51, 0x8D, 0xD1, 0x73, 0xF6, 0x80, 0x27, 0xF7, 0xFF, 0xEB, 0x25, 0x56, 0x54, 0xE0, 0x21, 0x1D, 0xE9, 0x21, 0x25, 0xDE, 0x2F, 0x4A, 0xD4, 0xFF, 0x14, 0xD3, 0xFF, 0xC9, 0x2F, 0x52, 0xD3, 0x2B, 0x3D, 0xC9, 0xFF, 0x54, 0xC8, 0x25, 0x49, 0xBD, 0x21, 0x07, 0xFC, 0x27, 0x46, 0xF0, 0xFF, 0x51, 0xE6, 0x20, 0x2D, 0xE2, 0x25, 0x9E, 0xD5, 0xFF, 0xE3, 0x21, 0x95, 0x55, 0xD6, 0x2D, 0xB0, 0xD0, 0x20, 0x21, 0xC3, 0x25, 0x10, 0xDA, 0x21, 0x3B, 0x14, 0xCD, 0xFF, 0xC5, 0x21, 0x4D, 0xC4, 0x25, 0x7B, 0xB6, 0xFF, 0x40, 0xBF, 0x21, 0x3D, 0xB2, 0xFF, 0xAB, 0xFF, 0xB0, 0xFF, 0x05, 0xA9, 0xFF, 0xA3, 0xFF, 0x9C, 0x21, 0x51, 0xC0, 0x22, 0x4A, 0x54, 0xB5, 0x21, 0x53, 0xAE, 0x21, 0xA8, 0xA2, 0x21, 0x59, 0xAA, 0xFF, 0x50, 0xA8, 0x20, 0xC8, 0xA0, 0x2F, 0xE0, 0x95, 0xFF, 0x8C, 0xFF, 0x40, 0xA6, 0x2B, 0x49, 0x9A, 0xFF, 0x92, 0xFF, 0x96, 0xFF, 0x54, 0x8F, 0x25, 0x33, 0x84, 0x20, 0x05, 0x87, 0x22, 0x2C, 0x7C, 0xFF, 0x15, 0x7F, 0xFF, 0x79, 0x2B, 0x43, 0x6E, 0x22, 0x86, 0xB8, 0x20, 0x4B, 0x46, 0xAA, 0x20, 0x53, 0xAD, 0xFF, 0xA4, 0x21, 0x00, 0x30, 0x53, 0x96, 0x2A, 0xFF, 0x90, 0x2B, 0xFF, 0x92, 0x20, 0xFC, 0x85, 0x20, 0x4B, 0xA4, 0x20, 0xFF, 0x9B, 0x20, 0x3D, 0xA0, 0xFF, 0x9D, 0xFF, 0x93, 0x82, 0x20, 0x17, 0x8D, 0xFF, 0x89, 0xFF, 0x80, 0x20, 0x3F, 0x86, 0x28, 0xFF, 0x83, 0x20, 0x41, 0x76, 0x20, 0x0D, 0x83, 0xFF, 0x7D, 0x0A, 0xFF, 0x77, 0xFF, 0x7E, 0x20, 0x4F, 0x72, 0x25, 0x87, 0x72, 0x02, 0xFF, 0x6C, 0xFF, 0x67, 0xFF, 0x62, 0x40, 0x03, 0x5C, 0x00, 0xFF, 0x58, 0xFF, 0x74, 0xFF, 0x70, 0xFF, 0x69, 0x28, 0xFF, 0x65, 0x25, 0xA1, 0x6A, 0x20, 0x15, 0x5F, 0xFF, 0x5E, 0x02, 0xFF, 0x5A, 0xFF, 0x53, 0xFF, 0x50, 0x22, 0x6C, 0x54, 0x0A, 0xFF, 0x4D, 0xFF, 0x4A, 0x00, 0xD3, 0xFF, 0x16, 0x24, 0x1D, 0x6B, 0x35, 0xFF, 0x15, 0x22, 0x66, 0x72, 0xD7, 0x85, 0x2F, 0xA8, 0xED, 0x5F, 0x95, 0x55, 0xF9, 0x2E, 0xCE, 0xF0, 0x94, 0x3F, 0x75, 0x21, 0xBF, 0xD5, 0x84, 0x4D, 0x6A, 0x3D, 0x2F, 0xD0, 0xAF, 0xAC, 0xFD, 0x22, 0xFB, 0xE8, 0x26, 0x3B, 0xE0, 0xAA, 0x2F, 0xE7, 0xF8, 0x2F, 0x06, 0xF1, 0x23, 0x03, 0xD9, 0x23, 0x01, 0xD3, 0xAA, 0x21, 0x7F, 0xF0, 0x28, 0xC8, 0xE6, 0x21, 0x77, 0xD6, 0x23, 0x0F, 0xCC, 0xAA, 0x22, 0xD1, 0xDD, 0x21, 0x89, 0xD5, 0x22, 0xBF, 0xC3, 0x22, 0xF6, 0xBB, 0xAA, 0x22, 0xB1, 0xBF, 0x21, 0x61, 0xB5, 0x22, 0xB1, 0xA8, 0x21, 0x59, 0x9F, 0xAA, 0x22, 0xBB, 0xAB, 0x21, 0x69, 0xA2, 0x21, 0x5F, 0x95, 0x2D, 0x23, 0x8C, 0xAD, 0x42, 0xD5, 0xD2, 0x21, 0x9F, 0xBF, 0x21, 0x95, 0x30, 0x1B, 0xCB, 0x27, 0x21, 0x55, 0xC4, 0x21, 0xA7, 0xB0, 0x21, 0x9D, 0xA9, 0x21, 0x9F, 0xA6, 0x21, 0x7D, 0x55, 0x9E, 0x21, 0x7F, 0x8F, 0x23, 0xA2, 0x87, 0x21, 0x77, 0x96, 0x26, 0xB9, 0xA8, 0x30, 0x0B, 0x7F, 0x21, 0x19, 0x78, 0x21, 0x7F, 0x9E, 0xFF, 0x94, 0xA2, 0x20, 0x01, 0x8A, 0x26, 0xCF, 0x82, 0xFF, 0x81, 0x20, 0x11, 0x8B, 0xB1, 0x20, 0x05, 0x82, 0x20, 0x19, 0x30, 0x1B, 0x6E, 0xFF, 0x66, 0x21, 0xA5, 0x51, 0x71, 0x21, 0x41, 0x68, 0x21, 0x3D, 0x63, 0xFF, 0x60, 0x21, 0x3B, 0x50, 0x66, 0x21, 0x41, 0x5E, 0x2D, 0xBD, 0x57, 0xFF, 0x51, 0xFF, 0x15, 0x4F, 0xFF, 0x48, 0x21, 0xC5, 0x70, 0x20, 0x21, 0x68, 0x80, 0x17, 0x55, 0x6A, 0x20, 0x25, 0x63, 0x21, 0x63, 0x57, 0x20, 0x1D, 0x50, 0x20, 0x1F, 0x10, 0x55, 0xFF, 0x4E, 0x20, 0x01, 0x46, 0xFF, 0x47, 0xFF, 0x05, 0x40, 0xFF, 0x3F, 0xFF, 0x39, 0x20, 0x07, 0x3F, 0x20, 0x09, 0x51, 0x39, 0x20, 0x09, 0x32, 0x20, 0x01, 0x2C, 0xFF, 0x5D, 0x23, 0xF6, 0x60, 0x53, 0x20, 0x23, 0x30, 0x03, 0x49, 0xFF, 0x44, 0xFF, 0x4B, 0x08, 0xFF, 0x45, 0xFF, 0x42, 0x21, 0x3E, 0x40, 0xFF, 0x3C, 0x02, 0xFF, 0x38, 0xFF, 0x34, 0xFF, 0x4A, 0x20, 0x39, 0x41, 0xA8, 0x21, 0x4E, 0x43, 0x20, 0x05, 0x3B, 0x20, 0x11, 0x38, 0xFF, 0x35, 0x00, 0xFF, 0x31, 0xFF, 0x2E, 0xFF, 0x33, 0xFF, 0x30, 0x2A, 0xFF, 0x2B, 0x23, 0x46, 0x3B, 0x20, 0x0F, 0x33, 0x20, 0x0F, 0x30, 0x82, 0x24, 0xD2, 0x2A, 0xFF, 0x26, 0xFF, 0x2D, 0x2B, 0x94, 0x27, 0x80, 0x2D, 0xA5, 0x23, 0xFF, 0x20, 0xFF, 0x1E, 0xFF, 0x1B, 0xA8, 0x23, 0x68, 0x26, 0x40, 0x0B, 0x24, 0x2D, 0xB9, 0x1E, 0xFF, 0x1C, 0x02, 0xFF, 0x1D, 0xFF, 0x1A, 0xFF, 0x18, 0x21, 0xD2, 0x18, 0x8A, 0x24, 0xB8, 0x13, 0xFF, 0x12, 0x33, 0x8B, 0x00, 0x20, 0x36, 0xD2, 0xDA, 0x6B, 0xF6, 0x34, 0x85, 0x00, 0x24, 0x87, 0x64, 0xB3, 0xFA, 0x2C, 0x0B, 0xEA, 0xAA, 0x24, 0x61, 0xE4, 0x24, 0x57, 0xCC, 0x24, 0x59, 0xC6, 0x27, 0xFF, 0xDF, 0xA9, 0x24, 0x75, 0xDA, 0x24, 0x5F, 0xC1, 0x24, 0x4D, 0xBC, 0x00, 0x22, 0xB6, 0x62, 0x00, 0x23, 0x56, 0x43, 0x7B, 0xFE, 0xFF, 0xF2, 0x34, 0xA5, 0x00, 0xD5, 0x23, 0x4E, 0x24, 0xFD, 0xED, 0x2A, 0x35, 0xEA, 0x2C, 0x67, 0xD5, 0x24, 0xE9, 0x55, 0xD2, 0x24, 0x91, 0xB7, 0x24, 0x8F, 0xB2, 0x29, 0x02, 0xCD, 0x24, 0xA5, 0x55, 0xCA, 0x25, 0x7E, 0xAF, 0x24, 0x81, 0xAB, 0x25, 0x86, 0xB0, 0x23, 0x01, 0x55, 0xAA, 0x23, 0x4B, 0x96, 0x23, 0x4D, 0x90, 0x23, 0x5B, 0xA4, 0x23, 0x09, 0x55, 0x9F, 0x2E, 0xFF, 0x8A, 0x23, 0x35, 0x85, 0x22, 0xED, 0x7D, 0x22, 0xE9, 0x55, 0x77, 0x22, 0xDB, 0x67, 0x22, 0xD9, 0x62, 0x22, 0xE7, 0x72, 0x23, 0x39, 0x55, 0x6D, 0x22, 0xE3, 0x5C, 0x22, 0xE5, 0x57, 0x23, 0x6B, 0x9A, 0x23, 0x37, 0x55, 0x96, 0x23, 0x17, 0x80, 0x23, 0x19, 0x7C, 0x23, 0x77, 0x93, 0x23, 0x29, 0x55, 0x90, 0x25, 0x4A, 0x79, 0x23, 0x21, 0x76, 0x22, 0xFF, 0x6A, 0x23, 0x01, 0x55, 0x65, 0x24, 0x7A, 0x53, 0x22, 0xF9, 0x50, 0x28, 0xA9, 0x62, 0x23, 0x09, 0x55, 0x5F, 0x25, 0x6C, 0x4D, 0x23, 0x01, 0x4A, 0x21, 0x7F, 0x53, 0x25, 0x78, 0x51, 0x4E, 0x21, 0x77, 0x42, 0x21, 0x79, 0x3D, 0xFF, 0x52, 0x21, 0x85, 0x55, 0x4E, 0x21, 0x87, 0x40, 0x21, 0x7D, 0x3C, 0x21, 0x7F, 0x3A, 0x21, 0x69, 0x55, 0x35, 0x21, 0x6F, 0x2D, 0x25, 0xA4, 0x28, 0x2E, 0xFD, 0x30, 0x21, 0x65, 0x55, 0x2C, 0x41, 0x53, 0x1E, 0x21, 0x61, 0x1B, 0x21, 0x9F, 0x41, 0x21, 0xDD, 0x55, 0x3D, 0x21, 0xAB, 0x31, 0x21, 0x99, 0x2D, 0x21, 0xA7, 0x3B, 0x21, 0xAF, 0x55, 0x38, 0x21, 0x9F, 0x2B, 0x21, 0xA1, 0x29, 0x24, 0xE8, 0x23, 0x21, 0x95, 0x55, 0x20, 0x21, 0x77, 0x18, 0x21, 0x79, 0x15, 0x21, 0x87, 0x1E, 0x2F, 0x43, 0x55, 0x1C, 0x21, 0x83, 0x13, 0x23, 0x5E, 0x12, 0x2F, 0x4F, 0x1D, 0x40, 0x1B, 0x45, 0x19, 0x23, 0x6C, 0x14, 0xFF, 0x11, 0x26, 0x72, 0x14, 0x23, 0x76, 0x54, 0x11, 0x20, 0x09, 0x0E, 0x20, 0x01, 0x0B, 0x21, 0xA3, 0x10, 0xFF, 0x10, 0x0F, 0xFF, 0x0D, 0x40, 0x03, 0x0B, 0xFF, 0x0A, 0xFF, 0x55, 0x0C, 0x20, 0x03, 0x09, 0x25, 0x24, 0x08, 0x25, 0x28, 0x06, 0x25, 0x32, 0x55, 0x13, 0x20, 0x1D, 0x10, 0x20, 0x1F, 0x0C, 0x20, 0x15, 0x0A, 0x25, 0x3C, 0x55, 0x0F, 0x20, 0x33, 0x0D, 0x20, 0x27, 0x08, 0x20, 0x1D, 0x07, 0x25, 0x52, 0xAB, 0x50, 0x25, 0x04, 0x20, 0x01, 0x03, 0x25, 0x76, 0x02, 0x80, 0x07, 0x50, 0x01, 0x56, 0x01, 0x00, 0xB9, 0x7F, 0x20, 0x2C, 0x1D, 0x03, 0x04, 0xE9, 0x7F, 0x10, 0x04, 0x80, 0x59, 0x30, 0x18, 0xC2, 0xFE, 0xE2, 0x2C, 0x3A, 0x3A, 0x46, 0x20, 0xF8, 0xE9, 0x06, 0xFF, 0x00, 0x95, 0x00, 0xDC, 0x00, 0x3E, 0x2E, 0x03, 0x1F, 0xA9, 0x80, 0x0C, 0xF2, 0x00, 0x10, 0xF9, 0x38, 0xEF, 0x4F, 0x02, 0x50, 0x90, 0x0F, 0xFF, 0xFF, 0xC0, 0xD0, 0x00, 0xDE, 0x98, 0xBF, 0x1B, 0xCB, 0xFF, 0x2F, 0x23, 0xF1, 0xF2, 0x7F, 0x4B, 0xFF, 0x01, 0xCF, 0x27, 0x10, 0x5B, 0x20, 0x2B, 0x10, 0x00, 0x11, 0x49, 0x71, 0x7E, 0x11, 0x60, 0x07, 0xF9, 0x7E, 0x70, 0x17, 0x0B, 0x10, 0x1F, 0x3A, 0x6E, 0x0C, 0xBA, 0x5C, 0x40, 0x80, 0x41, 0xCD, 0x30, 0xE3, 0xFF, 0x20, 0xF9, 0xB7, 0xFF, 0x00, 0xFF, 0xAF, 0xCF, 0x03, 0xD1, 0xF8, 0xFF, 0x7F, 0x00, 0xFE, 0xFF, 0x0C, 0x05, 0x06, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x90, 0x80, 0xED, 0xFF, 0xEE, 0xFF, 0x05, 0x79, 0x00, 0x77, 0x00, 0xEE, 0x20, 0x07, 0x77, 0x20, 0x07, 0x00, 0x00, 0xAA, 0x00, 0x07, 0xFF, 0xFF, 0x3F, 0xCF, 0x83, 0x2B, 0x90, 0xA5, 0x00, 0x00, 0xF9, 0xF8, 0x70, 0x17, 0x80, 0x1F, 0x00, 0x4A, 0x00, 0xA0, 0x6F, 0x6F, 0xF0, 0x30, 0x00, 0x03, 0x9B, 0x00, 0x00, 0xEF, 0x23, 0x00, 0x80, 0x37, 0x80, 0x3F, 0xC5, 0xEA, 0x05, 0x00, 0x30, 0x1F, 0x80, 0xE8, 0xAB, 0x59, 0xF7, 0x59, 0x00, 0x60, 0x3F, 0xF0, 0x3B, 0xFC, 0x6B, 0xF2, 0x00, 0xE0, 0x5F, 0x00, 0x90, 0x7F, 0xA2, 0x00, 0x6A, 0xF4, 0x15, 0xF3, 0x9F, 0x8F, 0x90, 0xBF, 0xDE, 0x20, 0xDF, 0x97, 0xDC, 0x48, 0x00, 0x01, 0x20, 0x10, 0x7B, 0xFF, 0x02, 0xAF, 0xFC, 0x10, 0x30, 0xFF, 0xFA, 0x39, 0xE3, 0x4E, 0xFF, 0x00, 0x04, 0x00, 0x00, 0x65, 0x50, 0x01, 0xA9, 0x88, 0x05, 0x04, 0x01, 0xFF, 0xF6, 0x1E, 0x8F, 0xB0, 0x50, 0xEF, 0x00, 0x4A, 0x9F, 0x25, 0x01, 0x05, 0x08, 0x3C, 0x8F, 0x70, 0x90, 0x21, 0xCF, 0x70, 0xA1, 0xFA, 0x86, 0x41, 0x45, 0xFF, 0xEF, 0x02, 0x00, 0x20, 0xC5, 0x2A, 0xD9, 0x80, 0x40, 0x80, 0x30, 0x03, 0xFF, 0xFE, 0x05, 0x0B, 0xF8, 0xE1, 0x40, 0x6F, 0x2B, 0x97, 0x80, 0x90, 0x00, 0x05, 0x60, 0x00, 0x80, 0x2F, 0x66, 0xB6, 0xFF, 0xFF, 0x25, 0x06, 0x06, 0x1F, 0x04, 0xF8, 0xF8, 0x9F, 0xF8, 0xF7, 0x2F, 0x73, 0x06, 0x07, 0x48, 0xBB, 0x21, 0x06, 0xD0, 0x40, 0x3B, 0xBB, 0xB8, 0x00, 0x6F, 0x00, 0x6F, 0x70, 0xF0, 0x6F, 0x6F, 0xE0, 0xE0, 0x68, 0x01, 0xDF, 0x50, 0xA0, 0xDF, 0xDF, 0x90, 0x90, 0x20, 0x0B, 0x04, 0xF0, 0x4B, 0x00, 0xB0, 0x00, 0x20, 0x0B, 0xA0, 0x9B, 0x00, 0x00, 0x70, 0x00, 0x89, 0xFF, 0xB6, 0x8D, 0xFF, 0x00, 0xFF, 0x04, 0x03, 0xAD, 0xFD, 0x23, 0x2F, 0xF3, 0x12, 0xF3, 0x9F, 0xAF, 0x20, 0x0B, 0x04, 0xBB, 0x2D, 0xB5, 0xF3, 0x00, 0xF3, 0xAF, 0xBF, 0xB2, 0x00, 0x8B, 0x00, 0xE8, 0x00, 0xB0, 0xFF, 0xEF, 0xC0, 0xC0, 0xFF, 0xFF, 0x49, 0x06, 0x10, 0x81, 0xFD, 0x90, 0xC1, 0x2B, 0x9B, 0x20, 0x0B, 0x90, 0x00, 0x00, 0xBB, 0x00, 0xA0, 0x21, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xB3, 0x00, 0xCC, 0x07, 0x7C, 0xFA, 0x68, 0x00, 0xAC, 0xFB, 0x89, 0x00, 0x0A, 0x95, 0xFA, 0x5F, 0x00, 0x48, 0xF8, 0xF9, 0x03, 0x06, 0x72, 0xFA, 0xBD, 0x00, 0x21, 0x9D, 0x01, 0x17, 0x0D, 0xF9, 0xF9, 0x01, 0x00, 0x00, 0xB7, 0x00, 0x58, 0xDF, 0xDB, 0xD8, 0x4F, 0x00, 0x3F, 0x30, 0x20, 0x3A, 0xFF, 0x00, 0x03, 0xFF, 0x00, 0xFF, 0x38, 0x6A, 0x4F, 0x4F, 0x20, 0x30, 0x3B, 0x82, 0x2E, 0x19, 0xFF, 0xFF, 0x4A, 0x0B, 0xBB, 0x2E, 0x18, 0x70, 0x00, 0xFA, 0xCC, 0x5E, 0xFF, 0xFF, 0x09, 0x08, 0xFA, 0x00, 0xFA, 0x8F, 0x8F, 0xF3, 0xF3, 0x8F, 0x7F, 0xFF, 0x00, 0xFC, 0x08, 0x3D, 0x91, 0x00, 0xDD, 0x00, 0xF3, 0x00, 0xF9, 0x8F, 0x9F, 0xBA, 0x00, 0x6B, 0x00, 0x00, 0x00, 0xB0, 0xC7, 0xAF, 0xF4, 0xF7, 0x6F, 0x7F, 0xDC, 0x00, 0x70, 0x19, 0xDF, 0x30, 0x30, 0xFF, 0xFF, 0xF5, 0x00, 0xC0, 0x6F, 0x9F, 0x10, 0x00, 0xD8, 0x00, 0x30, 0x00, 0x60, 0xFF, 0xEF, 0xDB, 0x12, 0x2A, 0x00, 0x31, 0x90, 0x2E, 0x70, 0x09, 0x0C, 0x34, 0xF2, 0xFF, 0xFE, 0x00, 0x10, 0x11, 0xFD, 0xFF, 0x09, 0x5B, 0xEB, 0x40, 0x40, 0xB0, 0x20, 0x2B, 0x06, 0xFF, 0x9F, 0x1E, 0x08, 0x09, 0x20, 0x1F, 0xAE, 0x7F, 0x05, 0x84, 0x09, 0xE4, 0x31, 0x40, 0x00, 0xFF, 0xE4, 0x3F, 0x49, 0x9F, 0xFF, 0x03, 0x02, 0xBF, 0xFA, 0x30, 0xFF, 0xC8, 0x00, 0x0F, 0x49, 0x23, 0xFC, 0xBF, 0x24, 0x02, 0xEE, 0x24, 0x02, 0x40, 0x07, 0x00, 0x05, 0xFA, 0x60, 0x17, 0x70, 0x1F, 0x00, 0x05, 0xFA, 0xB0, 0x09, 0x90, 0x1F, 0x87, 0xD0, 0xBF, 0x55, 0xFA, 0x20, 0xFB, 0xF9, 0xFF, 0x01, 0xFF, 0x8C, 0xAF, 0x03, 0xFF, 0x5E, 0x04, 0x10, 0x16, 0x4D, 0xE6, 0x01, 0x43, 0x4C, 0x49, 0x4D, 0xFF, 0xFE, 0x14, 0x2F, 0xFF, 0x18, 0x02, 0x02, 0x28, 0x26, 0xF7, 0x38, 0x90, 0x69, 0x6D, 0x61, 0x54, 0x67, 0x37, 0x02, 0x80, 0x27, 0xBE, 0x0D, 0x67, 0x0F, 0x9C, 0x6D, 0x00, 0xF7, 0xA2, 0xC3, 0x19, 0x7A, 0x1E, 0xE4, 0xC4, 0x00, 0x31, 0xB6, 0x92, 0x11, 0x0E, 0x96, 0xE4, 0xD2, 0x00, 0xE7, 0xF3, 0x4C, 0xB3, 0xFF, 0x51, 0x7C, 0x7E, 0x00, 0x52, 0x2C, 0x8D, 0x15, 0xC5, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char iQue_without_ISBN_LZ[0x2000] =
+{
+ 0x11, 0x48, 0x65, 0x00, 0x00, 0x64, 0x61, 0x72, 0x63, 0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x28, 0x65, 0x00, 0x00, 0x83, 0x30, 0x09, 0x1C, 0x04, 0x00, 0x00, 0x40, 0x20, 0x03, 0x30, 0x13, 0xAB, 0x30, 0x18, 0x15, 0x20, 0x1D, 0x02, 0xA0, 0x0B, 0x06, 0x20, 0x2B, 0x30, 0x18, 0x5A, 0x09, 0x20, 0x35, 0x10, 0x20, 0x39, 0x30, 0x2B, 0xF8, 0x20, 0x41, 0x54, 0x85, 0x30, 0x0B, 0x05, 0x00, 0x00, 0xEC, 0x20, 0x4D, 0x98, 0x30, 0x17, 0xD0, 0x20, 0x28, 0x30, 0x17, 0xDC, 0x30, 0x23, 0x07, 0x00, 0x00, 0xCC, 0x09, 0x0C, 0x00, 0x00, 0x20, 0x20, 0x51, 0x20, 0x14, 0x20, 0x2B, 0xA0, 0x20, 0x0B, 0x64, 0x20, 0x5D, 0x80, 0x20, 0x00, 0x00, 0x4C, 0x99, 0x20, 0x5C, 0xA8, 0x01, 0x50, 0x53, 0x20, 0x22, 0x00, 0xB2, 0x20, 0x75, 0x34, 0xE0, 0x22, 0x20, 0x13, 0x20, 0x74, 0xE2, 0x20, 0x81, 0xA0, 0x25, 0x13, 0x00, 0x00, 0x3C, 0x20, 0x68, 0x12, 0x02, 0x50, 0x77, 0x30, 0x8F, 0x41, 0x1C, 0x20, 0x90, 0x00, 0x36, 0x00, 0x00, 0x28, 0x20, 0xAB, 0x4D, 0x3E, 0x20, 0x9C, 0x80, 0x3A, 0x20, 0x0B, 0x20, 0xAD, 0x60, 0x30, 0x17, 0x54, 0x3C, 0x50, 0x17, 0x82, 0x30, 0x17, 0x40, 0x20, 0x23, 0x08, 0x00, 0x2D, 0x00, 0xA4, 0x30, 0x2F, 0x49, 0x20, 0x67, 0x20, 0xE9, 0xC4, 0x30, 0x3B, 0x56, 0x4A, 0x50, 0x17, 0xDC, 0x30, 0x3B, 0x52, 0x20, 0x47, 0x20, 0xE0, 0xF4, 0xB2, 0x30, 0x53, 0x55, 0x20, 0x53, 0x30, 0xD4, 0x00, 0x2E, 0x21, 0x13, 0x61, 0x02, 0x00, 0x6E, 0x00, 0x69, 0x00, 0x6D, 0x21, 0x1D, 0x4E, 0x82, 0x20, 0x07, 0x6E, 0x00, 0x74, 0x00, 0x65, 0x20, 0x11, 0x64, 0x0A, 0x00, 0x6F, 0x00, 0x4C, 0x20, 0x03, 0x67, 0x20, 0x07, 0x5F, 0x28, 0x00, 0x44, 0x20, 0x03, 0x30, 0x20, 0x01, 0x5F, 0x00, 0x53, 0x20, 0x00, 0x63, 0x40, 0x1F, 0x65, 0x00, 0x4F, 0x00, 0x75, 0xAB, 0x20, 0x2B, 0x41, 0x20, 0x43, 0x62, 0x20, 0x13, 0x6C, 0x40, 0x47, 0x02, 0x50, 0x43, 0x57, 0x42, 0x03, 0x20, 0x43, 0x43, 0x01, 0x80, 0x87, 0x55, 0x03, 0x20, 0xCB, 0x00, 0x90, 0x43, 0x01, 0x90, 0xCB, 0xD7, 0x00, 0x90, 0x87, 0xF0, 0xCB, 0x62, 0x21, 0x5D, 0x79, 0x21, 0x97, 0x01, 0x31, 0xA1, 0x71, 0x8D, 0xEA, 0x00, 0xF0, 0x2F, 0x71, 0x05, 0xD0, 0x2F, 0x74, 0x42, 0x09, 0x67, 0x23, 0x29, 0x33, 0xBD, 0x22, 0x01, 0x73, 0xA2, 0x01, 0xB0, 0x5B, 0x52, 0x2D, 0x00, 0x10, 0x21, 0x31, 0x01, 0x00, 0x21, 0x55, 0x32, 0x01, 0x00, 0x43, 0x33, 0xE0, 0x65, 0x4C, 0x23, 0x71, 0x4D, 0x22, 0xA3, 0x1F, 0x73, 0x00, 0x6B, 0x00, 0x40, 0x85, 0x30, 0x1F, 0x00, 0xB0, 0x17, 0xF0, 0x93, 0xF2, 0xE3, 0x41, 0x5F, 0x20, 0xB5, 0x32, 0x00, 0x38, 0x00, 0x78, 0x23, 0x68, 0x60, 0x34, 0xE0, 0xE1, 0x70, 0x02, 0x43, 0x4C, 0x41, 0x4E, 0xFF, 0x46, 0xFE, 0x23, 0xD0, 0x00, 0x02, 0x02, 0x34, 0x03, 0x33, 0x96, 0x70, 0x1D, 0x61, 0x74, 0x31, 0x23, 0x82, 0x44, 0x3E, 0x34, 0x59, 0x28, 0x33, 0x73, 0x10, 0xFF, 0xFF, 0xFF, 0x34, 0x4C, 0x53, 0x63, 0x65, 0x6E, 0x04, 0x65, 0x4F, 0x75, 0x74, 0x41, 0x24, 0x71, 0x47, 0x5F, 0x0C, 0x41, 0x5F, 0x30, 0x30, 0xA0, 0x4C, 0x40, 0x3B, 0x69, 0x31, 0xCD, 0x33, 0xA3, 0x50, 0x3F, 0x02, 0x00, 0x30, 0x59, 0x34, 0x9D, 0x68, 0x24, 0xA1, 0x00, 0x50, 0x5F, 0x4E, 0x69, 0x6E, 0x4C, 0x6F, 0x67, 0x70, 0x6F, 0xA0, 0x35, 0x34, 0xA0, 0x34, 0xBD, 0x43, 0x4C, 0x56, 0x43, 0x8F, 0x74, 0x3F, 0x00, 0x10, 0x02, 0x40, 0x87, 0x40, 0x0B, 0xD0, 0x5D, 0x20, 0x76, 0x20, 0x7F, 0x43, 0x34, 0xEC, 0x4E, 0x5F, 0x52, 0x6F, 0x6F, 0x73, 0x74, 0xD0, 0x7E, 0x00, 0x70, 0x4B, 0x80, 0x57, 0x00, 0x20, 0x20, 0x3B, 0x50, 0x3F, 0xF8, 0x00, 0x30, 0xFF, 0x34, 0xF7, 0xB0, 0xFF, 0x24, 0xD2, 0x80, 0xFF, 0x00, 0x00, 0x1E, 0xD5, 0x45, 0x4C, 0x70, 0xFF, 0x42, 0x40, 0xFF, 0x42, 0x00, 0x40, 0xFF, 0x9C, 0x80, 0x2D, 0xB2, 0x90, 0xFF, 0x5C, 0x01, 0xE0, 0xFF, 0x90, 0xB3, 0x34, 0xC2, 0x02, 0xD0, 0xF3, 0xC8, 0xFD, 0x20, 0xAA, 0xD0, 0xF3, 0x00, 0x70, 0xFF, 0xF1, 0xFF, 0x31, 0x39, 0x71, 0xFF, 0x65, 0x23, 0x31, 0xC5, 0xB1, 0xFF, 0x31, 0x84, 0x47, 0x5F, 0x43, 0x00, 0x81, 0xFF, 0x0F, 0xE1, 0xFF, 0x99, 0x02, 0x90, 0xFF, 0x12, 0xC3, 0x02, 0x31, 0xF3, 0x92, 0x3F, 0x80, 0xBF, 0x91, 0xF3, 0x7B, 0x60, 0x32, 0xB6, 0x00, 0x80, 0xFF, 0x36, 0xDF, 0x03, 0x32, 0xFF, 0x7C, 0x27, 0x27, 0x53, 0x3F, 0x55, 0x0D, 0x42, 0xFF, 0x48, 0x27, 0x9D, 0xB0, 0x27, 0xA1, 0xA4, 0x27, 0x8D, 0x60, 0x24, 0x27, 0x88, 0x36, 0xCB, 0x30, 0x03, 0x00, 0x00, 0xBC, 0xAD, 0x20, 0x03, 0x24, 0x27, 0xAB, 0x88, 0x37, 0x73, 0x27, 0x94, 0xB0, 0x26, 0xE7, 0x02, 0x74, 0x0A, 0x00, 0x00, 0x78, 0x0B, 0x32, 0xDF, 0x57, 0xF9, 0x00, 0x03, 0x5B, 0x37, 0x32, 0x27, 0x6E, 0x26, 0xB1, 0x33, 0xB7, 0x50, 0x41, 0x83, 0x2F, 0x71, 0x02, 0xF2, 0xE3, 0x73, 0xDB, 0x01, 0x13, 0x07, 0x50, 0x5F, 0x33, 0x00, 0x80, 0x67, 0x77, 0xB8, 0x60, 0x67, 0x20, 0xAA, 0x43, 0xC7, 0x38, 0x63, 0xC7, 0x30, 0x6F, 0x93, 0x9F, 0x53, 0xA0, 0x24, 0x0A, 0xA0, 0x27, 0xA5, 0x80, 0xBE, 0x24, 0x39, 0x23, 0x16, 0x23, 0xA0, 0xC0, 0x48, 0x79, 0x06, 0x02, 0x00, 0x30, 0x37, 0x70, 0x23, 0x00, 0x33, 0x33, 0xB3, 0x3F, 0xFC, 0x2D, 0xEC, 0xBC, 0x8C, 0x70, 0x0B, 0x0A, 0xD7, 0x23, 0x20, 0x0B, 0x30, 0x2F, 0x80, 0x3F, 0xBC, 0x48, 0xA9, 0x07, 0x01, 0xD0, 0x2F, 0xF4, 0x2F, 0xB0, 0x6B, 0x39, 0x0C, 0x40, 0x9D, 0x6F, 0x1C, 0x30, 0x97, 0x61, 0xEF, 0xCC, 0x28, 0x45, 0x30, 0x9B, 0x70, 0xF3, 0x24, 0x87, 0xDC, 0xE4, 0xB9, 0x71, 0x5B, 0x50, 0xF1, 0x5B, 0x29, 0x39, 0xD4, 0x8B, 0x70, 0xC1, 0x14, 0xCD, 0xCC, 0xCC, 0x20, 0xEB, 0x20, 0x24, 0x02, 0xF8, 0xC1, 0xF9, 0x00, 0x31, 0x67, 0x00, 0x14, 0xBB, 0x30, 0x7F, 0x30, 0x2F, 0x71, 0x73, 0x44, 0x73, 0xF5, 0x38, 0x94, 0x01, 0x90, 0x7F, 0x3C, 0xC2, 0x20, 0x7F, 0x3E, 0x02, 0xD0, 0x7F, 0x52, 0x65, 0x70, 0x64, 0x01, 0x70, 0xFF, 0xC1, 0xEB, 0x45, 0x43, 0xC2, 0xB7, 0x6D, 0xDB, 0xAE, 0x20, 0x7F, 0x8C, 0x25, 0x02, 0x20, 0x00, 0x40, 0xFF, 0x91, 0xF7, 0xB6, 0x1B, 0x5C, 0xA0, 0xA4, 0x87, 0xB4, 0x35, 0x3E, 0x00, 0x92, 0x24, 0xE9, 0xC0, 0xBD, 0x60, 0x8B, 0x31, 0x00, 0x32, 0xE7, 0x35, 0x33, 0xF2, 0xE7, 0x92, 0x53, 0xF0, 0x26, 0x82, 0x7F, 0x20, 0x25, 0x1B, 0x90, 0x0B, 0x50, 0x97, 0x34, 0xEF, 0x00, 0x50, 0x97, 0x96, 0x53, 0x30, 0x3B, 0xAF, 0x77, 0x04, 0xAA, 0xF1, 0x17, 0x32, 0x02, 0x13, 0x73, 0x32, 0xF7, 0x50, 0x8B, 0x00, 0x96, 0x7B, 0xF9, 0x33, 0x1B, 0x57, 0x78, 0x00, 0x31, 0x7F, 0x3B, 0x90, 0x57, 0x07, 0x54, 0x53, 0x2A, 0xEE, 0xB7, 0x47, 0x73, 0x4C, 0x37, 0x8B, 0x2B, 0xD9, 0x94, 0x63, 0x8B, 0x3B, 0x87, 0x3B, 0xD1, 0x61, 0x24, 0x4B, 0xD5, 0x00, 0x01, 0x97, 0xC0, 0x39, 0x8E, 0xE3, 0x2B, 0x39, 0xE8, 0x51, 0x5B, 0x5B, 0xFD, 0x01, 0x20, 0x23, 0x03, 0xF7, 0x6B, 0x40, 0x41, 0x9E, 0x11, 0x15, 0x8D, 0xBD, 0x31, 0xA3, 0x9A, 0x99, 0xB9, 0x2B, 0x7D, 0xAA, 0x2C, 0x5A, 0x04, 0x01, 0x10, 0x23, 0x01, 0x01, 0x20, 0x8F, 0x01, 0x01, 0x20, 0x8F, 0x01, 0xAD, 0x00, 0x10, 0x8F, 0xC1, 0x20, 0x8F, 0x3D, 0x60, 0x8F, 0x44, 0x5B, 0x01, 0x00, 0x10, 0x8F, 0x82, 0x00, 0x00, 0x23, 0x50, 0x5F, 0x42, 0x6C, 0x6B, 0x03, 0xE1, 0x63, 0x9A, 0x03, 0x99, 0x19, 0xC0, 0x0E, 0x74, 0xDA, 0x00, 0xC1, 0x63, 0x00, 0x40, 0x23, 0xFE, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0x00, 0x40, 0x23, 0x03, 0x81, 0x63, 0x00, 0x13, 0xBB, 0x00, 0x32, 0xC7, 0x58, 0xAA, 0x2E, 0x9D, 0x88, 0x66, 0x4F, 0xE8, 0x2E, 0xA9, 0x18, 0x2E, 0x95, 0x48, 0xBE, 0x2E, 0x99, 0x78, 0x62, 0xC7, 0xE3, 0xD3, 0x56, 0x3F, 0x60, 0x0B, 0x52, 0xD3, 0xF0, 0xF7, 0xC2, 0xD3, 0x01, 0xC0, 0x2F, 0x22, 0xDF, 0xD4, 0x33, 0x40, 0x68, 0x03, 0x50, 0x0B, 0x52, 0xEB, 0x7F, 0xF0, 0xC2, 0xEB, 0x01, 0xB0, 0x2F, 0x32, 0xF7, 0x01, 0xB0, 0xBF, 0x33, 0x03, 0x01, 0xC0, 0x2F, 0x00, 0x10, 0xBF, 0xFF, 0x46, 0x73, 0x70, 0x0B, 0x53, 0x1B, 0x40, 0xBF, 0x83, 0x1B, 0x01, 0xB0, 0x2F, 0x63, 0x27, 0x03, 0xC1, 0xC3, 0xFF, 0x33, 0x27, 0x75, 0x97, 0x93, 0x33, 0x00, 0x91, 0xC3, 0x01, 0x00, 0x2F, 0x05, 0xE1, 0xC3, 0x00, 0xF0, 0xBF, 0xF1, 0xC3, 0xFF, 0x01, 0x00, 0x2F, 0x05, 0x01, 0xC3, 0x00, 0x16, 0xB7, 0x00, 0x36, 0x4F, 0x35, 0xCC, 0x33, 0x8B, 0x36, 0x53, 0x33, 0x8F, 0x5F, 0xA0, 0x69, 0xE3, 0xD0, 0x6D, 0xAB, 0xE6, 0xCF, 0x59, 0xC7, 0x26, 0x43, 0x00, 0x40, 0x17, 0xFF, 0x26, 0x37, 0xD6, 0xFF, 0x63, 0x57, 0x26, 0x2B, 0x00, 0x30, 0x17, 0x36, 0x1F, 0x00, 0x30, 0x5F, 0x36, 0x13, 0xFF, 0x00, 0x40, 0x17, 0x00, 0x10, 0x5F, 0x49, 0x6B, 0x35, 0xFB, 0x00, 0x30, 0x17, 0x65, 0xEF, 0x03, 0xC1, 0x03, 0x82, 0xC7, 0xFF, 0xE1, 0x03, 0x82, 0xDF, 0x02, 0xE1, 0x03, 0x73, 0x27, 0xF1, 0x03, 0x80, 0x17, 0x01, 0xE1, 0x03, 0x00, 0xFD, 0xDF, 0x6E, 0x54, 0xEC, 0xDF, 0x02, 0x7E, 0xDF, 0x04, 0x2F, 0xA4, 0x5F, 0x0D, 0xDC, 0xDF, 0x50, 0xAA, 0x2F, 0xCC, 0xB8, 0x2F, 0xD0, 0x20, 0x2F, 0xBC, 0xA0, 0x2F, 0xC0, 0x2C, 0xAA, 0x2C, 0xE3, 0xAC, 0x2C, 0xE7, 0x10, 0x2C, 0xDF, 0x74, 0x2C, 0xDF, 0xD8, 0x5F, 0x07, 0x2D, 0x17, 0x09, 0x2C, 0x31, 0x2C, 0xE3, 0x02, 0x9C, 0xDF, 0x3E, 0xCF, 0x00, 0xFC, 0xDF, 0xD7, 0x9E, 0xF3, 0x00, 0xBC, 0xDF, 0x7C, 0xEC, 0xDF, 0x2C, 0x6D, 0x5B, 0xDD, 0x4F, 0x4C, 0xE3, 0xFF, 0x8C, 0xD3, 0xD0, 0x17, 0x9C, 0xBB, 0x00, 0x30, 0x17, 0x00, 0x9F, 0xD3, 0x3F, 0xFD, 0x01, 0x1C, 0x8B, 0x00, 0x0D, 0xE7, 0xBF, 0xC3, 0xA3, 0xA0, 0x2C, 0x7B, 0x00, 0x5C, 0x7F, 0xD0, 0x23, 0x01, 0x1C, 0x73, 0x03, 0xD0, 0x67, 0x02, 0x7C, 0x5B, 0x6F, 0x70, 0x2B, 0xCB, 0x7C, 0x5B, 0x20, 0x3B, 0xDB, 0x00, 0xED, 0x5B, 0x3E, 0x67, 0x7F, 0xD7, 0xEF, 0x5B, 0xCF, 0x00, 0xFC, 0x4F, 0x00, 0xDC, 0xDB, 0xF0, 0x2D, 0xCB, 0x80, 0x7F, 0x01, 0x2C, 0xDB, 0x30, 0x2F, 0xBF, 0x7F, 0xFB, 0xC8, 0x2F, 0x03, 0x7C, 0xDB, 0x5B, 0xE7, 0xAC, 0xDB, 0x00, 0x4C, 0x4F, 0x03, 0x3D, 0x67, 0xFF, 0x00, 0x1E, 0x67, 0xDD, 0x67, 0x04, 0x1C, 0x67, 0x41, 0xA3, 0x79, 0x93, 0x9D, 0x43, 0xCC, 0x67, 0x00, 0x60, 0x23, 0xFF, 0xCC, 0x67, 0x31, 0xEB, 0x89, 0x7B, 0x28, 0x2F, 0x00, 0x3C, 0x67, 0x00, 0x50, 0x23, 0xDC, 0x67, 0x00, 0x50, 0x8F, 0xFF, 0xDC, 0x67, 0x00, 0x60, 0x23, 0x00, 0x10, 0x8F, 0x79, 0x4B, 0x30, 0x8F, 0x00, 0x2C, 0x67, 0x00, 0x50, 0x23, 0x04, 0x1C, 0x67, 0x3F, 0x70, 0xC2, 0xA9, 0x33, 0x00, 0x81, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0xFF, 0x00, 0x40, 0x23, 0x03, 0x81, 0x63, 0x01, 0x5C, 0x67, 0x01, 0x9F, 0x2F, 0x43, 0xEB, 0x6F, 0x2F, 0x9F, 0x97, 0xDF, 0x2F, 0xFF, 0x00, 0x60, 0x23, 0xCF, 0x2F, 0x34, 0x33, 0x7F, 0x2F, 0x38, 0x2F, 0x00, 0x3F, 0x2F, 0x00, 0x50, 0x23, 0xDF, 0x2F, 0xFF, 0x00, 0x50, 0x8F, 0xDF, 0x2F, 0x00, 0x60, 0x23, 0x00, 0x10, 0x8F, 0x6F, 0x2F, 0x40, 0x8F, 0x00, 0x2F, 0x2F, 0x00, 0x50, 0x23, 0xFF, 0x01, 0x7C, 0x07, 0x01, 0xB1, 0x63, 0x9F, 0x2F, 0x00, 0x91, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0xFF, 0x00, 0x40, 0x23, 0x03, 0x81, 0x63, 0x01, 0x5B, 0xA7, 0x01, 0x95, 0x8F, 0x46, 0x27, 0x6F, 0x23, 0x9F, 0xDF, 0xD5, 0x8F, 0xFF, 0x00, 0x60, 0x23, 0xC5, 0x8F, 0x4F, 0xDF, 0x6F, 0x0B, 0x4F, 0xDF, 0x00, 0x25, 0x8F, 0x00, 0x50, 0x23, 0xD5, 0x8F, 0xFF, 0x00, 0x50, 0x8F, 0xD5, 0x8F, 0x00, 0x60, 0x23, 0x00, 0x10, 0x8F, 0x6E, 0xDB, 0x40, 0x8F, 0x00, 0x25, 0x8F, 0x00, 0x50, 0x23, 0xFF, 0x01, 0x7C, 0x07, 0x01, 0xB1, 0x63, 0x9E, 0xC3, 0x00, 0x91, 0x63, 0x00, 0x40, 0x23, 0x04, 0x61, 0x63, 0x00, 0x30, 0x8F, 0xF1, 0x63, 0xEF, 0x00, 0x40, 0x23, 0x03, 0x61, 0x63, 0x00, 0x7C, 0x5F, 0x4C, 0x2C, 0x5C, 0xBC, 0x5F, 0x3E, 0x51, 0x7C, 0x5F, 0x18, 0x65, 0x00, 0x73, 0xCC, 0x5F, 0x3B, 0x9C, 0x47, 0x5F, 0x43, 0xAF, 0x00, 0x4C, 0x5F, 0xFC, 0x2E, 0xBB, 0x0F, 0x5B, 0x58, 0x4C, 0x5F, 0x3C, 0x82, 0x3B, 0xAB, 0x55, 0xBC, 0x2F, 0xFF, 0xFC, 0x2F, 0xF8, 0x3C, 0x2E, 0xDB, 0x7C, 0x2E, 0xDF, 0x7C, 0xBC, 0x2E, 0xE3, 0x00, 0x3C, 0x47, 0x3E, 0xC7, 0x5E, 0xFB, 0x00, 0x7A, 0x3B, 0x80, 0xBF, 0xBD, 0x9A, 0x3B, 0x60, 0x88, 0xC7, 0x00, 0x3C, 0x2B, 0x00, 0x70, 0x4B, 0x9F, 0x2B, 0xCA, 0x2A, 0xB7, 0xDF, 0x00, 0x9B, 0xCB, 0x01, 0x10, 0x3F, 0xF2, 0xA0, 0x3F, 0x00, 0x1B, 0xA3, 0x01, 0xD0, 0x3F, 0x00, 0x29, 0xEF, 0x01, 0x00, 0xBF, 0x7B, 0x8E, 0x2B, 0x77, 0x70, 0xFF, 0x00, 0x27, 0x67, 0x01, 0x00, 0xFF, 0x24, 0xF0, 0x3F, 0xDF, 0x83, 0xB2, 0x01, 0x01, 0x3F, 0x30, 0x00, 0x8E, 0xBB, 0x5E, 0xBF, 0x59, 0x54, 0x7E, 0xBF, 0xA8, 0xA1, 0x2E, 0xBC, 0x10, 0x2F, 0xFB, 0x6C, 0x79, 0x74, 0x31, 0x3E, 0xD1, 0x90, 0x4A, 0x9E, 0x00, 0xA0, 0x2D, 0xE7, 0x70, 0x43, 0x74, 0x78, 0x36, 0x6C, 0x31, 0x3F, 0xDF, 0x3F, 0xBF, 0x04, 0x2F, 0xFF, 0x2D, 0x55, 0x74, 0x00, 0x65, 0x6E, 0x64, 0x6F, 0x5F, 0x31, 0x32, 0x38, 0x00, 0x78, 0x36, 0x34, 0x2E, 0x62, 0x63, 0x6C, 0x69, 0x57, 0x6D, 0x2F, 0xFF, 0x6D, 0x2E, 0xFB, 0x60, 0x62, 0x23, 0x30, 0x4B, 0x4D, 0x7F, 0x08, 0x4C, 0x6F, 0x67, 0x6F, 0xAE, 0xE9, 0xFF, 0xFF, 0xFF, 0xDF, 0x30, 0x03, 0x00, 0x40, 0x02, 0x15, 0x5F, 0xE0, 0x30, 0x62, 0xAF, 0x72, 0x3E, 0x07, 0x5E, 0x0B, 0x08, 0x70, 0x61, 0x6E, 0x31, 0x3B, 0x4F, 0x01, 0x04, 0xFF, 0x00, 0x00, 0x52, 0x6F, 0x6F, 0x74, 0x50, 0x61, 0x6E, 0x70, 0x65, 0x00, 0xB0, 0xDF, 0x00, 0x50, 0x47, 0x50, 0xD3, 0x70, 0x61, 0x73, 0x31, 0xD3, 0x3B, 0xA3, 0x70, 0x53, 0x03, 0x20, 0x53, 0x4E, 0x5F, 0x30, 0x55, 0x00, 0x0F, 0x96, 0xD0, 0x01, 0x20, 0x53, 0x4C, 0xD3, 0x42, 0x80, 0x53, 0x69, 0x63, 0x31, 0x80, 0x9F, 0x3C, 0x0F, 0x07, 0xFF, 0x00, 0x41, 0x03, 0x7E, 0xE0, 0x2D, 0x5B, 0x82, 0x1F, 0x00, 0x20, 0xEF, 0x9E, 0x2F, 0x63, 0x80, 0x42, 0xF1, 0x2B, 0x71, 0x99, 0xCF, 0x23, 0xC1, 0x27, 0x80, 0x0C, 0x3F, 0x70, 0x61, 0x65, 0x60, 0xDB, 0x50, 0x07, 0x67, 0x72, 0x30, 0x70, 0x31, 0x3C, 0x97, 0x31, 0x33, 0x47, 0x72, 0x6F, 0x75, 0xCE, 0x3C, 0x8F, 0x7F, 0xE7, 0x67, 0x72, 0x51, 0x07, 0x30, 0x23, 0x34, 0x57, 0x47, 0x3F, 0x5F, 0x41, 0xCF, 0xD3, 0x3F, 0xCF, 0xF1, 0x17, 0xF1, 0xD7, 0x30, 0x5F, 0x3F, 0xDF, 0x1F, 0x47, 0x5F, 0x42, 0xCF, 0x6D, 0x3F, 0xE7, 0x00, 0x90, 0x2B, 0xD4, 0x9F, 0x3F, 0xFB, 0x9A, 0xF1, 0x7F, 0x67, 0x72, 0x50, 0xC7, 0x01, 0x32, 0xBF, 0x3C, 0x22, 0xBC, 0x22, 0xB5, 0x00, 0x02, 0xBF, 0xC8, 0x82, 0xBF, 0x3D, 0x7F, 0x07, 0x64, 0xBB, 0x2D, 0x2F, 0xFF, 0x9D, 0x2F, 0x08, 0x00, 0x4F, 0x34, 0xA1, 0x32, 0xF3, 0x2F, 0xFF, 0x78, 0x2F, 0xFB, 0x1D, 0x33, 0x64, 0x73, 0x62, 0xAD, 0x62, 0xD2, 0x80, 0x10, 0x31, 0xF0, 0x10, 0x53, 0x32, 0xF0, 0x21, 0x33, 0x63, 0x05, 0x4C, 0x54, 0x90, 0x3E, 0x30, 0x0B, 0x83, 0x70, 0x39, 0x4C, 0x54, 0x4D, 0x61, 0x73, 0x3C, 0xCC, 0x63, 0x2D, 0x82, 0x33, 0x2B, 0xA8, 0x06, 0x00, 0x00, 0x0B, 0x2F, 0xFC, 0x38, 0xAA, 0x2F, 0xFF, 0x88, 0x2F, 0xFB, 0x08, 0x2F, 0xF4, 0x88, 0x2F, 0xF8, 0x08, 0xAA, 0x2F, 0xD4, 0x88, 0x2F, 0xD8, 0x4C, 0x2F, 0x10, 0xE8, 0x2F, 0x14, 0xAC, 0x9D, 0x23, 0x74, 0x48, 0x05, 0x2F, 0xD7, 0x20, 0x2F, 0x00, 0x35, 0x47, 0xAA, 0x53, 0x57, 0xBB, 0x00, 0x83, 0x53, 0x02, 0x00, 0xA3, 0x53, 0x00, 0x35, 0x57, 0x00, 0xB3, 0xA3, 0xD5, 0x20, 0xB3, 0x00, 0xB3, 0xA3, 0x68, 0x40, 0x24, 0x20, 0x30, 0x03, 0x11, 0x2F, 0xFB, 0x74, 0x06, 0x00, 0x61, 0x04, 0x30, 0x03, 0x30, 0x0B, 0x65, 0x06, 0x00, 0x01, 0x30, 0x03, 0xE9, 0x30, 0x17, 0x31, 0x87, 0x5E, 0x03, 0x05, 0x2F, 0x47, 0x4F, 0x5F, 0x31, 0x32, 0xB0, 0x01, 0xB0, 0x7F, 0x01, 0x03, 0xE0, 0x7F, 0xD2, 0xB5, 0x00, 0x00, 0x8C, 0x8C, 0x77, 0x8C, 0x05, 0xA0, 0x7F, 0x00, 0x16, 0x97, 0x00, 0xF1, 0x7F, 0x03, 0x03, 0xC1, 0x7F, 0x00, 0x16, 0xD7, 0x45, 0xA7, 0xCB, 0x2F, 0xB4, 0x00, 0x25, 0xA7, 0x80, 0x3F, 0x23, 0x44, 0x04, 0x25, 0xA3, 0x30, 0x03, 0x00, 0x06, 0x00, 0x06, 0x06, 0x73, 0x09, 0xED, 0xBE, 0xC3, 0x30, 0x03, 0x3F, 0xFB, 0x3A, 0x57, 0xDE, 0x40, 0x30, 0x03, 0xE0, 0x13, 0x70, 0xC0, 0x30, 0x03, 0x00, 0x75, 0xD3, 0x78, 0x54, 0x10, 0x04, 0x00, 0x01, 0x0A, 0x10, 0x04, 0x10, 0x02, 0xA2, 0x37, 0x46, 0xF2, 0x37, 0x26, 0x0F, 0x06, 0x02, 0x05, 0x66, 0x23, 0x33, 0x00, 0x12, 0x43, 0x4D, 0x5F, 0x00, 0x35, 0xB6, 0x96, 0x00, 0x36, 0x6A, 0x80, 0xEA, 0x23, 0x77, 0x05, 0x26, 0x67, 0x30, 0x03, 0x30, 0x1F, 0x8E, 0xE3, 0xBE, 0x30, 0x03, 0xB0, 0xBF, 0xE0, 0x13, 0xC0, 0xBF, 0x50, 0xA7, 0x78, 0x00, 0x00, 0xC0, 0xA7, 0x00, 0x21, 0x5F, 0xCF, 0x5F, 0x01, 0xB1, 0x5F, 0x2F, 0xA1, 0xBD, 0x61, 0xBF, 0x30, 0x03, 0x3F, 0xF7, 0xCE, 0x95, 0x17, 0x41, 0x30, 0x03, 0xBC, 0xE0, 0x13, 0xC1, 0x30, 0x03, 0x05, 0x21, 0x5F, 0x00, 0x00, 0xC3, 0x01, 0x31, 0x5F, 0x61, 0x0B, 0x3F, 0xB6, 0xBF, 0x30, 0x03, 0xB0, 0xBF, 0xE0, 0x13, 0xC0, 0xBF, 0x02, 0x61, 0x5F, 0xCD, 0xF7, 0xFF, 0x01, 0xB2, 0xBF, 0x3F, 0xF7, 0x50, 0x03, 0x5D, 0xA7, 0x50, 0x03, 0xC0, 0x13, 0x4F, 0xF7, 0x05, 0x22, 0xBF, 0xFF, 0x00, 0x00, 0xC3, 0x01, 0x32, 0xBF, 0x3F, 0xE3, 0x3F, 0xE7, 0xB0, 0xBF, 0xE0, 0x13, 0xC0, 0xBF, 0x01, 0xF2, 0xBF, 0xFF, 0x03, 0x59, 0x73, 0x57, 0x87, 0x00, 0x59, 0x73, 0x00, 0x1C, 0x63, 0x99, 0x1F, 0x40, 0x03, 0x00, 0x79, 0x1F, 0x3F, 0x93, 0xAC, 0xC9, 0x73, 0xA0, 0x4E, 0xC7, 0xF5, 0x00, 0x84, 0xD3, 0x70, 0x53, 0x46, 0x31, 0x74, 0x32, 0x00, 0x63, 0x2F, 0x58, 0x2F, 0xFA, 0x9F, 0x05, 0x4F, 0xF1, 0x00, 0x00, 0x13, 0xCD, 0xCC, 0x4C, 0x28, 0x36, 0x80, 0x3F, 0x50, 0x07, 0x40, 0x0F, 0xFF, 0x4A, 0x9B, 0x50, 0x07, 0x9F, 0xEC, 0xE0, 0x0B, 0x40, 0x03, 0x00, 0x0A, 0x1B, 0x2A, 0xC3, 0x00, 0xA4, 0xB7, 0xBE, 0x60, 0xFB, 0x20, 0x01, 0xC0, 0xA7, 0x27, 0x62, 0x01, 0x00, 0xA7, 0x8A, 0x1B, 0x81, 0x2F, 0x91, 0xC5, 0x00, 0x84, 0xA3, 0x71, 0x83, 0x10, 0xF4, 0xBF, 0x01, 0xC1, 0x2F, 0x07, 0x04, 0xD1, 0x2F, 0xDF, 0x00, 0x80, 0xA7, 0x01, 0xF1, 0x2F, 0x08, 0x02, 0x41, 0x2F, 0x00, 0x5D, 0x8B, 0xE1, 0xB7, 0xEB, 0xD7, 0x00, 0xD2, 0x5F, 0x77, 0x09, 0x04, 0xD2, 0x5F, 0x00, 0xB0, 0xA7, 0x01, 0xC3, 0x07, 0x0A, 0x01, 0xE2, 0x5F, 0x92, 0xE7, 0x00, 0x1F, 0xFB, 0xAD, 0xDD, 0x07, 0xA0, 0x00, 0x68, 0x1F, 0x10, 0x43, 0xE3, 0x00, 0x5D, 0x03, 0x50, 0x43, 0x83, 0x1F, 0x00, 0x00, 0x44, 0x6D, 0x03, 0x30, 0x0F, 0x3E, 0x2B, 0x30, 0x0F, 0x2D, 0x03, 0x9B, 0x6D, 0x83, 0x03, 0x05, 0x6D, 0x83, 0x00, 0x4D, 0xD6, 0xF8, 0x3F, 0x1F, 0x00, 0xA0, 0x7F, 0x5E, 0x80, 0x00, 0x40, 0x7F, 0x01, 0x01, 0x4D, 0x83, 0x00, 0x3E, 0x0B, 0x00, 0x1A, 0xEB, 0x01, 0x94, 0xEB, 0x80, 0x7B, 0x41, 0xFF, 0x37, 0x5F, 0xE9, 0x00, 0xEE, 0x0B, 0x7E, 0x8B, 0x01, 0x50, 0x7F, 0xFA, 0xEB, 0xBD, 0x02, 0xB0, 0x7F, 0x03, 0x8E, 0x8B, 0x9E, 0x7B, 0xFE, 0x9B, 0x00, 0x02, 0x0F, 0x03, 0x3F, 0x13, 0xFD, 0x00, 0x1A, 0xF3, 0x01, 0x51, 0x8F, 0x3F, 0x13, 0x00, 0x12, 0x0F, 0x2A, 0x3A, 0x04, 0x8F, 0x13, 0xDC, 0x00, 0x2F, 0x13, 0x7F, 0x0C, 0x4F, 0x13, 0xD6, 0xB7, 0xFD, 0x97, 0xFD, 0x57, 0xFC, 0xE7, 0xFC, 0x77, 0xFC, 0x07, 0xFE, 0xFB, 0x97, 0xFA, 0xE3, 0xFA, 0x57, 0xF9, 0xA3, 0xF9, 0x17, 0xF8, 0x63, 0x3F, 0xEF, 0xCC, 0xEB, 0x00, 0x2F, 0xB3, 0x3E, 0x8F, 0x0A, 0x30, 0xCB, 0x2C, 0x41, 0xA7, 0x43, 0xCF, 0x1B, 0x37, 0x0D, 0x98, 0xF8, 0x5F, 0x67, 0x72, 0x56, 0xFF, 0x04, 0x40, 0x02, 0x60, 0x00, 0x5A, 0x3C, 0xF8, 0xFA, 0x34, 0x9F, 0x2C, 0x5F, 0x4F, 0x27, 0x00, 0x0C, 0x91, 0x82, 0xA0, 0x00, 0xFC, 0xFF, 0x5F, 0x00, 0xFE, 0x00, 0xFF, 0x5A, 0xC0, 0x48, 0xBE, 0xED, 0x75, 0xDF, 0x00, 0x28, 0xF9, 0x20, 0xFF, 0x4C, 0xFE, 0x3F, 0xDD, 0x1A, 0xEF, 0x68, 0x74, 0x08, 0x40, 0x04, 0x20, 0x50, 0x84, 0x3F, 0xFF, 0xF6, 0x40, 0xFF, 0x26, 0x2F, 0xFF, 0x63, 0x03, 0x00, 0x00, 0xC0, 0xF4, 0x00, 0x10, 0xFD, 0xFF, 0xE8, 0x80, 0x2F, 0xB8, 0xF5, 0xF0, 0xFF, 0xFF, 0x20, 0x50, 0xFF, 0x12, 0xFF, 0x30, 0x20, 0x58, 0x09, 0x9F, 0x6F, 0x9F, 0xD9, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0x6F, 0xAF, 0xBF, 0xE9, 0xF2, 0x60, 0x86, 0x5F, 0xEF, 0x0E, 0x8F, 0xFF, 0xF9, 0x51, 0x37, 0x3F, 0xFF, 0xF5, 0x0C, 0xF2, 0xFF, 0xFF, 0xF2, 0x20, 0x03, 0x4F, 0xE3, 0x26, 0x00, 0x64, 0x22, 0x4F, 0xEB, 0x29, 0x82, 0xFF, 0x58, 0x28, 0xE3, 0x06, 0xFF, 0x06, 0xFF, 0x2F, 0x2F, 0x00, 0x00, 0x30, 0x03, 0x4F, 0xFF, 0x22, 0xA0, 0xA0, 0x1F, 0xC1, 0x50, 0x77, 0x0A, 0x0A, 0x00, 0x30, 0x0A, 0x14, 0x0A, 0xD0, 0xF3, 0x6F, 0xE6, 0x64, 0x4F, 0xEE, 0x46, 0x00, 0x20, 0x00, 0xE3, 0x24, 0x2A, 0x8F, 0x9F, 0x00, 0x66, 0xFF, 0x06, 0xF4, 0x2D, 0xDF, 0xC0, 0xC6, 0x90, 0x6F, 0xBF, 0xFB, 0x04, 0xC7, 0x01, 0x52, 0x1C, 0x20, 0xB7, 0x20, 0x00, 0xF0, 0x20, 0xEB, 0x30, 0x03, 0x2F, 0xB1, 0x60, 0xF8, 0x30, 0xCB, 0x20, 0xB6, 0xFF, 0x66, 0x00, 0x66, 0x00, 0x70, 0x02, 0x20, 0xE3, 0x20, 0x6E, 0x2F, 0xC7, 0x00, 0x04, 0xFF, 0xFF, 0x20, 0x0D, 0x8F, 0x7F, 0xDC, 0xF7, 0x30, 0xFF, 0xFD, 0x00, 0x00, 0x00, 0x30, 0x00, 0x19, 0xFF, 0x00, 0xAA, 0xE6, 0xC1, 0x61, 0xE7, 0x2E, 0xF9, 0xC0, 0xF5, 0xF9, 0xFF, 0xDF, 0x20, 0xD5, 0x00, 0x07, 0x10, 0xFC, 0xFC, 0xAF, 0xDF, 0xFF, 0x02, 0x21, 0x9F, 0x6F, 0x3A, 0x6E, 0x35, 0x00, 0xD7, 0x02, 0x30, 0x41, 0x18, 0x00, 0xFF, 0xFD, 0x40, 0xEF, 0x21, 0x3B, 0x00, 0x00, 0xF9, 0x00, 0xF2, 0x01, 0x0B, 0x20, 0x00, 0xCF, 0xFF, 0x21, 0x02, 0xFF, 0xA8, 0x00, 0x5A, 0x00, 0x20, 0x21, 0x63, 0x20, 0x80, 0x2F, 0xA5, 0x0B, 0x0A, 0xF6, 0xF6, 0x0A, 0x0C, 0xF6, 0x00, 0xF2, 0xF7, 0x8E, 0xFF, 0xFF, 0x21, 0x00, 0x69, 0x02, 0x00, 0x8F, 0xFF, 0xA2, 0x06, 0x12, 0x3F, 0xC3, 0x4F, 0x01, 0xFF, 0x00, 0xDF, 0xFF, 0x00, 0x1C, 0xFF, 0x3F, 0xCD, 0x00, 0x00, 0x00, 0xC3, 0xFF, 0xFC, 0xFF, 0xFF, 0x40, 0x00, 0x00, 0xA9, 0x00, 0xFB, 0xFF, 0xFF, 0x4F, 0x6A, 0xAB, 0x2F, 0x74, 0x0A, 0x3F, 0x7A, 0x09, 0x9F, 0xF9, 0x03, 0x04, 0x82, 0x70, 0xEF, 0xFE, 0x81, 0x7F, 0x9C, 0xF6, 0xFF, 0xFF, 0x10, 0x00, 0xC6, 0x3F, 0xA4, 0x1C, 0x6F, 0xFF, 0x00, 0xA0, 0x88, 0x05, 0x00, 0x8F, 0x01, 0x5C, 0xC1, 0x43, 0x4C, 0x04, 0x49, 0x4D, 0xFF, 0xFE, 0x14, 0x32, 0x7C, 0x02, 0x28, 0xC1, 0x29, 0xF7, 0x3B, 0x5D, 0x69, 0x6D, 0x61, 0x67, 0x10, 0x4B, 0xE4, 0x18, 0x20, 0x00, 0x0D, 0x42, 0x30, 0x07, 0x03, 0x8B, 0xA0, 0x00, 0x71, 0x05, 0x00, 0x88, 0xFE, 0xFF, 0xFF, 0x25, 0xCE, 0xC0, 0x2E, 0xCB, 0x01, 0xC0, 0xC0, 0xAF, 0x9F, 0x00, 0x00, 0x9F, 0x20, 0x03, 0x03, 0x00, 0x88, 0x00, 0x88, 0xFF, 0xCC, 0x20, 0x17, 0x70, 0x07, 0x81, 0xFF, 0xC0, 0x78, 0x00, 0x02, 0xFF, 0xFC, 0x3E, 0x4F, 0x9B, 0x87, 0x3F, 0xEE, 0x90, 0x90, 0xDF, 0xDF, 0x30, 0x03, 0x01, 0xA1, 0xD7, 0x40, 0x6F, 0xC8, 0x30, 0x6B, 0x40, 0x6F, 0x00, 0xB0, 0x43, 0xCF, 0xDF, 0xFF, 0x55, 0x0A, 0xFF, 0xD7, 0x00, 0xEE, 0x00, 0x0E, 0xCE, 0x55, 0x20, 0x17, 0xEE, 0xE8, 0x20, 0x17, 0x70, 0x07, 0x40, 0x6F, 0x80, 0x90, 0x6F, 0xC5, 0xFF, 0xCF, 0x1E, 0x7F, 0xDE, 0x00, 0x95, 0x9D, 0xC1, 0x7F, 0x2F, 0x63, 0xB1, 0x7F, 0x20, 0x3A, 0x00, 0x10, 0x51, 0x7F, 0xB9, 0x8A, 0x06, 0xC5, 0x30, 0x50, 0xA8, 0x42, 0x70, 0xC2, 0x28, 0x4E, 0x2E, 0x06, 0x10, 0x00, 0x43, 0xFD, 0x3A, 0xAF, 0x76, 0x24, 0x00, 0x98, 0x6F, 0xC8, 0xCE, 0x47, 0x2D, 0xA3, 0xFF, 0x7A, 0x22, 0xFF, 0x45, 0x4F, 0xFE, 0xAA, 0x00, 0xBB, 0x4A, 0xCF, 0xBB, 0x8A, 0x50, 0x07, 0xFF, 0x23, 0xEF, 0x3F, 0x96, 0x00, 0x23, 0xDE, 0x53, 0x8A, 0x4F, 0xFF, 0x9A, 0x00, 0x68, 0x4A, 0xEF, 0x24, 0x35, 0x23, 0xAD, 0x14, 0xFF, 0xFF, 0xC8, 0x3A, 0xFB, 0xB3, 0x33, 0x2F, 0xFF, 0xFF, 0x87, 0x66, 0x67, 0x27, 0xFF, 0x00, 0x4B, 0x83, 0x4F, 0x7B, 0xA7, 0x21, 0xD1, 0xE0, 0x2E, 0x0D, 0x37, 0xCA, 0x08, 0x46, 0x42, 0x21, 0xF6, 0x22, 0xFF, 0xF7, 0x44, 0xF7, 0x00, 0x15, 0x7F, 0x22, 0xFF, 0x32, 0x4F, 0x7A, 0x43, 0xFF, 0x60, 0x97, 0x6B, 0xE7, 0x36, 0x6A, 0x10, 0xE7, 0xF2, 0xF4, 0xFF, 0xF8, 0x34, 0xBA, 0x40, 0x03, 0x9F, 0x9B, 0x25, 0x32, 0x8F, 0xA8, 0x0C, 0x09, 0xFF, 0x40, 0x4F, 0x25, 0x2D, 0xAD, 0xBF, 0x04, 0x28, 0xFF, 0x00, 0x62, 0x6C, 0x06, 0xF4, 0x37, 0xFF, 0xCF, 0xD6, 0x00, 0xDD, 0x00, 0x4C, 0xFC, 0xDD, 0x35, 0x00, 0xEE, 0x34, 0x4A, 0x31, 0xEF, 0x54, 0x00, 0x45, 0x1F, 0xB8, 0x38, 0x0B, 0x48, 0x51, 0x41, 0xEF, 0xFD, 0xA0, 0x97, 0x1F, 0x10, 0x00, 0xFE, 0x18, 0xFC, 0x10, 0xA0, 0x23, 0xF1, 0x6F, 0xFF, 0x2C, 0xEF, 0x00, 0x05, 0x03, 0xFF, 0xFF, 0x1E, 0x8F, 0xA1, 0x1B, 0xEF, 0x21, 0x1F, 0xCE, 0xC7, 0x69, 0x04, 0xD8, 0x4B, 0xA1, 0xF2, 0x27, 0xCB, 0x20, 0x03, 0x7F, 0xD5, 0xE1, 0x84, 0x40, 0xD7, 0x37, 0xFF, 0x01, 0xBE, 0x4D, 0xAF, 0x58, 0x00, 0x44, 0x23, 0x4F, 0x7B, 0x64, 0xFF, 0xA7, 0x47, 0xEF, 0xDC, 0xFF, 0x59, 0xED, 0x79, 0xA0, 0xDE, 0x24, 0xA0, 0x37, 0x04, 0xCC, 0xFF, 0x50, 0xCF, 0x10, 0x21, 0x00, 0x32, 0x42, 0xDF, 0x33, 0x00, 0x33, 0x00, 0x13, 0x00, 0x73, 0x30, 0x26, 0xAA, 0xFF, 0xFF, 0x40, 0x04, 0x63, 0x3F, 0x9C, 0x46, 0xD7, 0x7A, 0xEF, 0x35, 0x94, 0x72, 0xEF, 0x26, 0xF5, 0x2F, 0x05, 0x5C, 0x4D, 0x2F, 0xCA, 0x6B, 0x03, 0xE4, 0x0C, 0x09, 0x55, 0xFF, 0x08, 0xC0, 0x7F, 0x91, 0x00, 0x01, 0x00, 0xF3, 0xF3, 0x00, 0x99, 0x00, 0x99, 0x5F, 0xB7, 0xFC, 0x20, 0x0B, 0x20, 0x0F, 0x8F, 0xC7, 0x70, 0x17, 0x60, 0x1F, 0x8F, 0xE7, 0x56, 0xFF, 0x34, 0x55, 0x01, 0x3A, 0xFD, 0x90, 0x1F, 0x78, 0x4F, 0xFF, 0x55, 0xFF, 0x46, 0x65, 0x4A, 0x2F, 0x97, 0xFF, 0xFC, 0x35, 0x5C, 0x29, 0x23, 0x02, 0xC6, 0x34, 0x07, 0x3F, 0xFF, 0x8B, 0xFF, 0x03, 0x44, 0x10, 0x28, 0x4D, 0xD4, 0xD0, 0x80, 0x5F, 0x3F, 0xF0, 0x17, 0x9F, 0xF5, 0xEF, 0xFF, 0x07, 0xCF, 0xD1, 0x45, 0x6F, 0x2B, 0x59, 0x3E, 0xFB, 0x5F, 0x30, 0x20, 0xFB, 0x5F, 0x87, 0x12, 0xF3, 0xF9, 0xF8, 0x90, 0x3F, 0x31, 0xB7, 0x22, 0x97, 0x00, 0x60, 0x75, 0x85, 0xBF, 0x2F, 0xFF, 0xAF, 0x0D, 0xFF, 0x9E, 0xFF, 0x45, 0x45, 0x4F, 0x79, 0xA9, 0x00, 0x9A, 0x45, 0xBF, 0x89, 0x55, 0xA7, 0x10, 0xFF, 0x22, 0xFF, 0x3E, 0x9F, 0x00, 0xFF, 0x75, 0xFF, 0x52, 0xDA, 0x4F, 0xE3, 0x23, 0x3A, 0xDB, 0x5E, 0x7F, 0x95, 0x9F, 0x7F, 0x3E, 0x8F, 0x52, 0x23, 0x0C, 0x0D, 0x92, 0x31, 0xE1, 0xEF, 0xE1, 0xFF, 0x7F, 0xC7, 0x02, 0xF8, 0x2C, 0xE9, 0x30, 0x03, 0xF0, 0x0F, 0x01, 0x1D, 0xA6, 0x45, 0x3E, 0x00, 0xFB, 0xB0, 0xB7, 0x3A, 0x47, 0xFE, 0x2B, 0x83, 0x8C, 0x57, 0xD0, 0x28, 0x8B, 0x25, 0x31, 0x77, 0x11, 0x60, 0x0D, 0xA5, 0x1B, 0x96, 0x44, 0x00, 0x00, 0xFC, 0xFB, 0x01, 0x30, 0x07, 0xF8, 0x3B, 0xB6, 0x56, 0x45, 0x0E, 0x50, 0x00, 0x2F, 0x51, 0x3F, 0x2C, 0x8F, 0xE5, 0x2C, 0xC3, 0x00, 0xFA, 0x30, 0x2B, 0xBB, 0x43, 0x6F, 0x76, 0x87, 0x18, 0xEF, 0x00, 0x38, 0x77, 0x77, 0xC2, 0x5F, 0x85, 0xAE, 0x4B, 0x6B, 0xFF, 0x01, 0xAF, 0x47, 0xCF, 0x15, 0x32, 0x6B, 0xDC, 0x26, 0x89, 0x00, 0x3E, 0x67, 0x3A, 0x0D, 0xB4, 0x2F, 0x04, 0xF1, 0xFF, 0x7F, 0xEB, 0xA0, 0xB0, 0xA1, 0x26, 0x73, 0xF4, 0x79, 0x7C, 0x00, 0x60, 0xFB, 0xFF, 0x28, 0x32, 0xC0, 0x00, 0xB0, 0x01, 0x24, 0x07, 0x4F, 0x08, 0x2F, 0x1F, 0x00, 0x00, 0x72, 0x0D, 0x3D, 0x04, 0x7D, 0xFB, 0xFE, 0xE5, 0x00, 0xD8, 0x5C, 0xA7, 0xA5, 0xB7, 0x3F, 0x93, 0x61, 0x00, 0x1C, 0xBF, 0x38, 0x93, 0x40, 0x96, 0x9E, 0x2A, 0x03, 0x4F, 0xF4, 0x4B, 0xFE, 0x28, 0xAF, 0xD0, 0xE1, 0x3E, 0xFF, 0x1A, 0x27, 0x87, 0x3E, 0x05, 0x18, 0x00, 0x00, 0x3F, 0x2B, 0x55, 0x98, 0xBE, 0x04, 0x07, 0xFF, 0x17, 0xFF, 0x08, 0x06, 0x0E, 0x53, 0xFF, 0x20, 0x4A, 0xBF, 0x3F, 0xB6, 0xB3, 0xFF, 0x1C, 0xDE, 0xFF, 0xDD, 0x55, 0x42, 0x60, 0x17, 0x7F, 0xD6, 0xDD, 0xFF, 0x03, 0xED, 0xFF, 0x00, 0x31, 0x00, 0x95, 0x7A, 0xDB, 0x60, 0x37, 0x24, 0xEE, 0x12, 0x2E, 0xBF, 0x50, 0xFD, 0xDA, 0x11, 0xFF, 0xBD, 0x24, 0xFF, 0x69, 0x45, 0xE7, 0x14, 0x6B, 0x9B, 0x0F, 0x8E, 0x5E, 0x34, 0x01, 0x9F, 0x6F, 0xD3, 0x00, 0x1C, 0x2A, 0x35, 0x2F, 0x8F, 0xFC, 0xFC, 0x09, 0x00, 0xAD, 0x00, 0x47, 0x5A, 0x6F, 0xFD, 0x74, 0x4E, 0x97, 0x1E, 0xB9, 0xFF, 0xDC, 0x4F, 0xFF, 0x2F, 0x44, 0x2B, 0xB2, 0x4F, 0x3C, 0xBB, 0x6A, 0xFF, 0x2B, 0xAA, 0x2D, 0x64, 0x10, 0x60, 0xB7, 0x32, 0x35, 0xDC, 0x10, 0x15, 0x00, 0xB4, 0xEC, 0x2F, 0xF3, 0xF9, 0x7B, 0x78, 0xEF, 0x68, 0x9F, 0x10, 0x8B, 0xFF, 0x25, 0xAB, 0x8F, 0x6D, 0xFF, 0x8F, 0x02, 0xBD, 0x4E, 0xDD, 0x6C, 0x01, 0xEC, 0xAC, 0xCE, 0x7F, 0x2D, 0x16, 0xBE, 0x7F, 0x80, 0x7E, 0x7F, 0xC0, 0x9D, 0x2E, 0x04, 0x0F, 0xBD, 0xFF, 0xEF, 0xEF, 0x8A, 0xAF, 0x8E, 0x00, 0x47, 0x24, 0xDD, 0x78, 0xDD, 0x77, 0x33, 0x11, 0x01, 0x33, 0x11, 0x8D, 0x7D, 0x13, 0x13, 0x7D, 0x20, 0x03, 0xBF, 0x8A, 0xBF, 0x77, 0x50, 0x17, 0x70, 0x07, 0xFF, 0xFF, 0x30, 0x2B, 0xB0, 0x2F, 0xF0, 0x0F, 0xB7, 0x01, 0xBF, 0x7F, 0xA8, 0x6D, 0xEA, 0x7F, 0x7F, 0x10, 0x6D, 0xFF, 0x27, 0xB0, 0x04, 0xA1, 0x00, 0xA0, 0x0D, 0xB0, 0x01, 0x02, 0x60, 0xED, 0x61, 0xFF, 0x2C, 0xFF, 0xBE, 0x35, 0xFF, 0xF0, 0x3E, 0xB7, 0x00, 0xC0, 0xFF, 0x19, 0x00, 0x21, 0x1D, 0x01, 0x28, 0xFA, 0x18, 0xCC, 0xFF, 0x3A, 0x3B, 0x92, 0x40, 0x3F, 0x17, 0xFF, 0x6B, 0x8D, 0x27, 0x4C, 0x84, 0xFF, 0xE9, 0xBD, 0xB9, 0x3C, 0xB8, 0xFD, 0x23, 0x34, 0xE2, 0x30, 0x62, 0x4C, 0xDA, 0x40, 0x13, 0xF7, 0xFF, 0xF1, 0x20, 0x03, 0xEF, 0x08, 0xFF, 0xE8, 0xFF, 0xE0, 0x20, 0x03, 0xE1, 0xFF, 0xD9, 0x38, 0xFF, 0xD3, 0x50, 0x95, 0x2E, 0xE1, 0x21, 0x87, 0x57, 0xFF, 0x86, 0x34, 0xFF, 0xD1, 0x93, 0x69, 0x30, 0x41, 0xFA, 0x31, 0x9F, 0xAC, 0xFF, 0x44, 0xC7, 0x41, 0xA5, 0xD9, 0xFF, 0xE4, 0x50, 0x5B, 0xF6, 0xFF, 0x41, 0xF2, 0x20, 0x5D, 0xFB, 0xFF, 0xEE, 0xFF, 0xEA, 0x2F, 0x23, 0x54, 0xF5, 0x20, 0x05, 0xE4, 0x23, 0x97, 0xEA, 0x2E, 0x2E, 0xDA, 0xFF, 0x10, 0xDB, 0xFF, 0xD5, 0x2C, 0x6E, 0xC6, 0xFF, 0xD0, 0xFF, 0x05, 0xCB, 0xFF, 0xC1, 0xFF, 0xBC, 0x27, 0xE7, 0xE1, 0x20, 0x11, 0x41, 0xD2, 0x24, 0x7A, 0xDA, 0xFF, 0xCD, 0xFF, 0xCA, 0x20, 0x19, 0x04, 0xC1, 0xFF, 0xB7, 0xFF, 0xB3, 0x20, 0xFE, 0xBA, 0xFF, 0x14, 0xAF, 0xFF, 0xAB, 0x05, 0xD1, 0xFF, 0x5F, 0x62, 0x6D, 0x03, 0xFF, 0x51, 0x29, 0x20, 0xC2, 0xC2, 0xE1, 0x7F, 0x05, 0xFF, 0x9F, 0x22, 0x8D, 0x5B, 0x07, 0x21, 0x61, 0xA7, 0x20, 0x9A, 0x5F, 0xE9, 0x8A, 0xD9, 0x48, 0x38, 0x99, 0x50, 0xFE, 0x41, 0x01, 0xF7, 0x25, 0x34, 0xEA, 0xFF, 0xE0, 0x8D, 0xA2, 0xD1, 0x73, 0xF6, 0x80, 0x27, 0xF7, 0xFF, 0xEB, 0x25, 0x56, 0xE0, 0xA8, 0x21, 0x1D, 0xE9, 0x21, 0x25, 0xDE, 0x2F, 0x4A, 0xD4, 0xFF, 0xD3, 0x28, 0xFF, 0xC9, 0x2F, 0x52, 0xD3, 0x2B, 0x3D, 0xC9, 0xFF, 0xC8, 0xA8, 0x25, 0x49, 0xBD, 0x21, 0x07, 0xFC, 0x27, 0x46, 0xF0, 0xFF, 0xE6, 0xA2, 0x20, 0x2D, 0xE2, 0x25, 0x9E, 0xD5, 0xFF, 0xE3, 0x21, 0x95, 0xD6, 0xAA, 0x2D, 0xB0, 0xD0, 0x20, 0x21, 0xC3, 0x25, 0x10, 0xDA, 0x21, 0x3B, 0xCD, 0x28, 0xFF, 0xC5, 0x21, 0x4D, 0xC4, 0x25, 0x7B, 0xB6, 0xFF, 0xBF, 0x80, 0x21, 0x3D, 0xB2, 0xFF, 0xAB, 0xFF, 0xB0, 0xFF, 0xA9, 0x0A, 0xFF, 0xA3, 0xFF, 0x9C, 0x21, 0x51, 0xC0, 0x22, 0x4A, 0xB5, 0xA8, 0x21, 0x53, 0xAE, 0x21, 0xA8, 0xA2, 0x21, 0x59, 0xAA, 0xFF, 0xA8, 0xA0, 0x20, 0xC8, 0xA0, 0x2F, 0xE0, 0x95, 0xFF, 0x8C, 0xFF, 0xA6, 0x80, 0x2B, 0x49, 0x9A, 0xFF, 0x92, 0xFF, 0x96, 0xFF, 0x8F, 0xA8, 0x25, 0x33, 0x84, 0x20, 0x05, 0x87, 0x22, 0x2C, 0x7C, 0xFF, 0x7F, 0x2A, 0xFF, 0x79, 0x2B, 0x43, 0x6E, 0x22, 0x86, 0xB8, 0x20, 0x4B, 0xAA, 0x8C, 0x20, 0x53, 0xAD, 0xFF, 0xA4, 0x21, 0x00, 0x30, 0x53, 0x96, 0xFF, 0x54, 0x90, 0x2B, 0xFF, 0x92, 0x20, 0xFC, 0x85, 0x20, 0x4B, 0xA4, 0xFF, 0x41, 0x9B, 0x20, 0x3D, 0xA0, 0xFF, 0x9D, 0xFF, 0x93, 0x20, 0x17, 0x04, 0x8D, 0xFF, 0x89, 0xFF, 0x80, 0x20, 0x3F, 0x86, 0xFF, 0x50, 0x83, 0x20, 0x41, 0x76, 0x20, 0x0D, 0x83, 0xFF, 0x7D, 0xFF, 0x14, 0x77, 0xFF, 0x7E, 0x20, 0x4F, 0x72, 0x25, 0x87, 0x72, 0xFF, 0x04, 0x6C, 0xFF, 0x67, 0xFF, 0x62, 0x40, 0x03, 0x5C, 0xFF, 0x00, 0x58, 0xFF, 0x74, 0xFF, 0x70, 0xFF, 0x69, 0xFF, 0x50, 0x65, 0x25, 0xA1, 0x6A, 0x20, 0x15, 0x5F, 0xFF, 0x5E, 0xFF, 0x04, 0x5A, 0xFF, 0x53, 0xFF, 0x50, 0x22, 0x6C, 0x54, 0xFF, 0x14, 0x4D, 0xFF, 0x4A, 0x00, 0xD3, 0xFF, 0x16, 0x24, 0x1D, 0x6B, 0xFF, 0x6A, 0x15, 0x22, 0x66, 0x72, 0xD7, 0x85, 0x2F, 0xA8, 0xED, 0x5F, 0x95, 0xF9, 0xAA, 0x2E, 0xCE, 0xF0, 0x94, 0x3F, 0x75, 0x21, 0xBF, 0xD5, 0x84, 0x4D, 0x3D, 0xD5, 0x2F, 0xD0, 0xAF, 0xAC, 0xFD, 0x22, 0xFB, 0xE8, 0x26, 0x3B, 0xE0, 0x2F, 0xE7, 0x55, 0xF8, 0x2F, 0x06, 0xF1, 0x23, 0x03, 0xD9, 0x23, 0x01, 0xD3, 0x21, 0x7F, 0x55, 0xF0, 0x28, 0xC8, 0xE6, 0x21, 0x77, 0xD6, 0x23, 0x0F, 0xCC, 0x22, 0xD1, 0x55, 0xDD, 0x21, 0x89, 0xD5, 0x22, 0xBF, 0xC3, 0x22, 0xF6, 0xBB, 0x22, 0xB1, 0x55, 0xBF, 0x21, 0x61, 0xB5, 0x22, 0xB1, 0xA8, 0x21, 0x59, 0x9F, 0x22, 0xBB, 0x55, 0xAB, 0x21, 0x69, 0xA2, 0x21, 0x5F, 0x95, 0x2D, 0x23, 0x8C, 0x42, 0xD5, 0x5A, 0xD2, 0x21, 0x9F, 0xBF, 0x21, 0x95, 0x30, 0x1B, 0xCB, 0x27, 0x21, 0xC4, 0xAA, 0x21, 0xA7, 0xB0, 0x21, 0x9D, 0xA9, 0x21, 0x9F, 0xA6, 0x21, 0x7D, 0x9E, 0xAB, 0x21, 0x7F, 0x8F, 0x23, 0xA2, 0x87, 0x21, 0x77, 0x96, 0x26, 0xB9, 0x30, 0x0B, 0x51, 0x7F, 0x21, 0x19, 0x78, 0x21, 0x7F, 0x9E, 0xFF, 0x94, 0x20, 0x01, 0x45, 0x8A, 0x26, 0xCF, 0x82, 0xFF, 0x81, 0x20, 0x11, 0x8B, 0x20, 0x05, 0x62, 0x82, 0x20, 0x19, 0x30, 0x1B, 0x6E, 0xFF, 0x66, 0x21, 0xA5, 0x71, 0xA2, 0x21, 0x41, 0x68, 0x21, 0x3D, 0x63, 0xFF, 0x60, 0x21, 0x3B, 0x66, 0xA0, 0x21, 0x41, 0x5E, 0x2D, 0xBD, 0x57, 0xFF, 0x51, 0xFF, 0x4F, 0x2A, 0xFF, 0x48, 0x21, 0xC5, 0x70, 0x20, 0x21, 0x68, 0x80, 0x17, 0x6A, 0xAA, 0x20, 0x25, 0x63, 0x21, 0x63, 0x57, 0x20, 0x1D, 0x50, 0x20, 0x1F, 0x55, 0x20, 0xFF, 0x4E, 0x20, 0x01, 0x46, 0xFF, 0x47, 0xFF, 0x40, 0x0A, 0xFF, 0x3F, 0xFF, 0x39, 0x20, 0x07, 0x3F, 0x20, 0x09, 0x39, 0xA2, 0x20, 0x09, 0x32, 0x20, 0x01, 0x2C, 0xFF, 0x5D, 0x23, 0xF6, 0x53, 0xC0, 0x20, 0x23, 0x30, 0x03, 0x49, 0xFF, 0x44, 0xFF, 0x4B, 0xFF, 0x10, 0x45, 0xFF, 0x42, 0x21, 0x3E, 0x40, 0xFF, 0x3C, 0xFF, 0x05, 0x38, 0xFF, 0x34, 0xFF, 0x4A, 0x20, 0x39, 0x41, 0x21, 0x4E, 0x50, 0x43, 0x20, 0x05, 0x3B, 0x20, 0x11, 0x38, 0xFF, 0x35, 0xFF, 0x00, 0x31, 0xFF, 0x2E, 0xFF, 0x33, 0xFF, 0x30, 0xFF, 0x55, 0x2B, 0x23, 0x46, 0x3B, 0x20, 0x0F, 0x33, 0x20, 0x0F, 0x30, 0x24, 0xD2, 0x05, 0x2A, 0xFF, 0x26, 0xFF, 0x2D, 0x2B, 0x94, 0x27, 0x2D, 0xA5, 0x01, 0x23, 0xFF, 0x20, 0xFF, 0x1E, 0xFF, 0x1B, 0x23, 0x68, 0x50, 0x26, 0x40, 0x0B, 0x24, 0x2D, 0xB9, 0x1E, 0xFF, 0x1C, 0xFF, 0x05, 0x1D, 0xFF, 0x1A, 0xFF, 0x18, 0x21, 0xD2, 0x18, 0x24, 0xB8, 0x15, 0x13, 0xFF, 0x12, 0x33, 0x8B, 0x00, 0x20, 0x36, 0xD2, 0x6B, 0xF6, 0xB5, 0x34, 0x85, 0x00, 0x24, 0x87, 0x64, 0xB3, 0xFA, 0x2C, 0x0B, 0xEA, 0x24, 0x61, 0x55, 0xE4, 0x24, 0x57, 0xCC, 0x24, 0x59, 0xC6, 0x27, 0xFF, 0xDF, 0x24, 0x75, 0x52, 0xDA, 0x24, 0x5F, 0xC1, 0x24, 0x4D, 0xBC, 0x00, 0x22, 0xB6, 0x00, 0xC5, 0x23, 0x56, 0x43, 0x7B, 0xFE, 0xFF, 0xF2, 0x34, 0xA5, 0x00, 0x23, 0x4E, 0xAA, 0x24, 0xFD, 0xED, 0x2A, 0x35, 0xEA, 0x2C, 0x67, 0xD5, 0x24, 0xE9, 0xD2, 0xAA, 0x24, 0x91, 0xB7, 0x24, 0x8F, 0xB2, 0x29, 0x02, 0xCD, 0x24, 0xA5, 0xCA, 0xAA, 0x25, 0x7E, 0xAF, 0x24, 0x81, 0xAB, 0x25, 0x86, 0xB0, 0x23, 0x01, 0xAA, 0xAA, 0x23, 0x4B, 0x96, 0x23, 0x4D, 0x90, 0x23, 0x5B, 0xA4, 0x23, 0x09, 0x9F, 0xAA, 0x2E, 0xFF, 0x8A, 0x23, 0x35, 0x85, 0x22, 0xED, 0x7D, 0x22, 0xE9, 0x77, 0xAA, 0x22, 0xDB, 0x67, 0x22, 0xD9, 0x62, 0x22, 0xE7, 0x72, 0x23, 0x39, 0x6D, 0xAA, 0x22, 0xE3, 0x5C, 0x22, 0xE5, 0x57, 0x23, 0x6B, 0x9A, 0x23, 0x37, 0x96, 0xAA, 0x23, 0x17, 0x80, 0x23, 0x19, 0x7C, 0x23, 0x77, 0x93, 0x23, 0x29, 0x90, 0xAA, 0x25, 0x4A, 0x79, 0x23, 0x21, 0x76, 0x22, 0xFF, 0x6A, 0x23, 0x01, 0x65, 0xAA, 0x24, 0x7A, 0x53, 0x22, 0xF9, 0x50, 0x28, 0xA9, 0x62, 0x23, 0x09, 0x5F, 0xAA, 0x25, 0x6C, 0x4D, 0x23, 0x01, 0x4A, 0x21, 0x7F, 0x53, 0x25, 0x78, 0x4E, 0xA2, 0x21, 0x77, 0x42, 0x21, 0x79, 0x3D, 0xFF, 0x52, 0x21, 0x85, 0x4E, 0xAA, 0x21, 0x87, 0x40, 0x21, 0x7D, 0x3C, 0x21, 0x7F, 0x3A, 0x21, 0x69, 0x35, 0xAA, 0x21, 0x6F, 0x2D, 0x25, 0xA4, 0x28, 0x2E, 0xFD, 0x30, 0x21, 0x65, 0x2C, 0xAA, 0x41, 0x53, 0x1E, 0x21, 0x61, 0x1B, 0x21, 0x9F, 0x41, 0x21, 0xDD, 0x3D, 0xAA, 0x21, 0xAB, 0x31, 0x21, 0x99, 0x2D, 0x21, 0xA7, 0x3B, 0x21, 0xAF, 0x38, 0xAA, 0x21, 0x9F, 0x2B, 0x21, 0xA1, 0x29, 0x24, 0xE8, 0x23, 0x21, 0x95, 0x20, 0xAA, 0x21, 0x77, 0x18, 0x21, 0x79, 0x15, 0x21, 0x87, 0x1E, 0x2F, 0x43, 0x1C, 0xAA, 0x21, 0x83, 0x13, 0x23, 0x5E, 0x12, 0x2F, 0x4F, 0x1D, 0x40, 0x1B, 0x19, 0x8A, 0x23, 0x6C, 0x14, 0xFF, 0x11, 0x26, 0x72, 0x14, 0x23, 0x76, 0x11, 0xA8, 0x20, 0x09, 0x0E, 0x20, 0x01, 0x0B, 0x21, 0xA3, 0x10, 0xFF, 0x0F, 0x20, 0xFF, 0x0D, 0x40, 0x03, 0x0B, 0xFF, 0x0A, 0xFF, 0x0C, 0xAA, 0x20, 0x03, 0x09, 0x25, 0x24, 0x08, 0x25, 0x28, 0x06, 0x25, 0x32, 0x13, 0xAA, 0x20, 0x1D, 0x10, 0x20, 0x1F, 0x0C, 0x20, 0x15, 0x0A, 0x25, 0x3C, 0x0F, 0xAB, 0x20, 0x33, 0x0D, 0x20, 0x27, 0x08, 0x20, 0x1D, 0x07, 0x25, 0x52, 0x50, 0x25, 0x56, 0x04, 0x20, 0x01, 0x03, 0x25, 0x76, 0x02, 0x80, 0x07, 0x50, 0x01, 0x01, 0xAC, 0x00, 0xB9, 0x7F, 0x20, 0x2C, 0x1D, 0x03, 0x04, 0xE9, 0x7F, 0x10, 0x04, 0x80, 0x59, 0x30, 0xC2, 0x30, 0xFE, 0xE2, 0x2C, 0x3A, 0x3A, 0x46, 0x20, 0xF8, 0xE9, 0xFF, 0x0C, 0x00, 0x95, 0x00, 0xDC, 0x00, 0x3E, 0x2E, 0x03, 0x1F, 0xA9, 0x80, 0xF2, 0x18, 0x00, 0x10, 0xF9, 0x38, 0xEF, 0x4F, 0x02, 0x50, 0x90, 0xFF, 0x1F, 0xFF, 0xC0, 0xD0, 0x00, 0xDE, 0x98, 0xBF, 0x1B, 0xCB, 0xFF, 0x2F, 0x23, 0xF2, 0x7F, 0xE2, 0x4B, 0xFF, 0x01, 0xCF, 0x27, 0x10, 0x5B, 0x20, 0x2B, 0x10, 0x00, 0x11, 0x49, 0x71, 0x11, 0xFD, 0x60, 0x07, 0xF9, 0x7E, 0x70, 0x17, 0x0B, 0x10, 0x1F, 0x3A, 0x6E, 0x0C, 0xBA, 0x5C, 0x40, 0x41, 0xCD, 0x00, 0x30, 0xE3, 0xFF, 0x20, 0xF9, 0xB7, 0xFF, 0xFF, 0x00, 0xAF, 0xCF, 0x03, 0xD1, 0xF8, 0xFF, 0x7F, 0xFE, 0x00, 0xFF, 0x0C, 0x05, 0x06, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x90, 0x80, 0xED, 0xFF, 0xEE, 0xFF, 0x79, 0x0A, 0x00, 0x77, 0x00, 0xEE, 0x20, 0x07, 0x77, 0x20, 0x07, 0x00, 0x01, 0xAA, 0x00, 0x07, 0xFF, 0xFF, 0x3F, 0xCF, 0x2B, 0x90, 0x06, 0xA5, 0x00, 0x00, 0xF9, 0xF8, 0x70, 0x17, 0x80, 0x1F, 0x4A, 0x00, 0x00, 0xA0, 0x6F, 0x6F, 0xF0, 0x30, 0x00, 0x9B, 0x07, 0x00, 0x00, 0xEF, 0x23, 0x00, 0x80, 0x37, 0x80, 0x3F, 0xEA, 0x05, 0x8B, 0x00, 0x30, 0x1F, 0x80, 0xE8, 0xAB, 0x59, 0xF7, 0x59, 0x00, 0x60, 0x3F, 0x3B, 0xFC, 0xE0, 0x6B, 0xF2, 0x00, 0xE0, 0x5F, 0x00, 0x90, 0x7F, 0xA2, 0x00, 0x6A, 0xF4, 0xF3, 0x2A, 0x9F, 0x8F, 0x90, 0xBF, 0xDE, 0x20, 0xDF, 0x97, 0xDC, 0x48, 0x01, 0x00, 0x20, 0x10, 0x7B, 0xFF, 0x02, 0xAF, 0xFC, 0x30, 0x20, 0xFF, 0xFA, 0x39, 0xE3, 0x4E, 0xFF, 0x00, 0x04, 0x00, 0x00, 0x65, 0x50, 0x01, 0xA9, 0x88, 0x05, 0x04, 0xFF, 0x02, 0xF6, 0x1E, 0x8F, 0xB0, 0x50, 0xEF, 0x00, 0x4A, 0x9F, 0x01, 0x4B, 0x05, 0x08, 0x3C, 0x8F, 0x70, 0x90, 0x21, 0xCF, 0x70, 0xA1, 0xFA, 0x41, 0x45, 0x0C, 0xFF, 0xEF, 0x02, 0x00, 0x20, 0xC5, 0x2A, 0xD9, 0x80, 0x80, 0x80, 0x30, 0x03, 0xFF, 0xFE, 0x05, 0x0B, 0xF8, 0xE1, 0x6F, 0x81, 0x2B, 0x97, 0x80, 0x90, 0x00, 0x05, 0x60, 0x00, 0x2F, 0x66, 0x00, 0xB6, 0xFF, 0xFF, 0x25, 0x06, 0x06, 0x1F, 0xF8, 0x08, 0xF8, 0x9F, 0xF8, 0xF7, 0x2F, 0x73, 0x06, 0x07, 0xBB, 0x90, 0x21, 0x06, 0xD0, 0x40, 0x3B, 0xBB, 0xB8, 0x00, 0x6F, 0x6F, 0x00, 0x70, 0xF0, 0x6F, 0x6F, 0xE0, 0xE0, 0x68, 0xDF, 0x02, 0x50, 0xA0, 0xDF, 0xDF, 0x90, 0x90, 0x20, 0x0B, 0xF0, 0x08, 0x4B, 0x00, 0xB0, 0x00, 0x20, 0x0B, 0xA0, 0x9B, 0x00, 0x00, 0x70, 0x00, 0x89, 0xFF, 0xB6, 0x8D, 0xFF, 0xFF, 0x00, 0x04, 0x03, 0xAD, 0xFD, 0x23, 0x2F, 0xF3, 0xF3, 0x24, 0x9F, 0xAF, 0x20, 0x0B, 0x04, 0xBB, 0x2D, 0xB5, 0xF3, 0xF3, 0x00, 0xAF, 0xBF, 0xB2, 0x00, 0x8B, 0x00, 0xE8, 0xB0, 0x00, 0xFF, 0xEF, 0xC0, 0xC0, 0xFF, 0xFF, 0x49, 0x10, 0x0C, 0x81, 0xFD, 0x90, 0xC1, 0x2B, 0x9B, 0x20, 0x0B, 0x90, 0x00, 0x00, 0xBB, 0x00, 0xA0, 0x21, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xB3, 0x00, 0xCC, 0x07, 0x7C, 0xFA, 0x68, 0xAC, 0x00, 0xFB, 0x89, 0x00, 0x0A, 0x95, 0xFA, 0x5F, 0x48, 0x00, 0xF8, 0xF9, 0x03, 0x06, 0x72, 0xFA, 0xBD, 0x21, 0x00, 0x9D, 0x01, 0x17, 0x0D, 0xF9, 0xF9, 0x01, 0x00, 0x00, 0xB7, 0x00, 0x58, 0xDF, 0xDB, 0xD8, 0x4F, 0x3F, 0x00, 0x30, 0x20, 0x3A, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x01, 0x38, 0x6A, 0x4F, 0x4F, 0x20, 0x30, 0x3B, 0x2E, 0x19, 0x04, 0xFF, 0xFF, 0x4A, 0x0B, 0xBB, 0x2E, 0x18, 0x70, 0xFA, 0x00, 0xCC, 0x5E, 0xFF, 0xFF, 0x09, 0x08, 0xFA, 0xFA, 0x00, 0x8F, 0x8F, 0xF3, 0xF3, 0x8F, 0x7F, 0xFF, 0xFC, 0x00, 0x08, 0x3D, 0x91, 0x00, 0xDD, 0x00, 0xF3, 0xF9, 0x00, 0x8F, 0x9F, 0xBA, 0x00, 0x6B, 0x00, 0x00, 0xB0, 0x00, 0xC7, 0xAF, 0xF4, 0xF7, 0x6F, 0x7F, 0xDC, 0x70, 0x00, 0x19, 0xDF, 0x30, 0x30, 0xFF, 0xFF, 0xF5, 0xC0, 0x00, 0x6F, 0x9F, 0x10, 0x00, 0xD8, 0x00, 0x30, 0x60, 0x01, 0xFF, 0xEF, 0xDB, 0x12, 0x2A, 0x00, 0x31, 0x2E, 0x70, 0x20, 0x09, 0x0C, 0x34, 0xF2, 0xFF, 0xFE, 0x00, 0x10, 0xFD, 0x22, 0xFF, 0x09, 0x5B, 0xEB, 0x40, 0x40, 0xB0, 0x20, 0x2B, 0xFF, 0x0D, 0x9F, 0x1E, 0x08, 0x09, 0x20, 0x1F, 0xAE, 0x7F, 0x05, 0x09, 0xE4, 0x31, 0x08, 0x40, 0x00, 0xFF, 0xE4, 0x3F, 0x49, 0x9F, 0xFF, 0x02, 0x07, 0xBF, 0xFA, 0x30, 0xFF, 0xC8, 0x00, 0x0F, 0x49, 0x23, 0xFC, 0x24, 0x02, 0x7F, 0xEE, 0x24, 0x02, 0x40, 0x07, 0x00, 0x05, 0xFA, 0x60, 0x17, 0x70, 0x1F, 0x00, 0x05, 0xFA, 0x09, 0x90, 0x1F, 0x60, 0x87, 0xD0, 0xBF, 0x55, 0xFA, 0x20, 0xFB, 0xF9, 0xFF, 0xFF, 0x02, 0x8C, 0xAF, 0x03, 0xFF, 0x5E, 0x04, 0x10, 0x16, 0x4D, 0xE6, 0x43, 0x02, 0x4C, 0x49, 0x4D, 0xFF, 0xFE, 0x14, 0x2F, 0xFF, 0x02, 0x30, 0x02, 0x28, 0x26, 0xF7, 0x38, 0x90, 0x69, 0x6D, 0x61, 0x67, 0xA8, 0x37, 0x02, 0x80, 0x27, 0xBE, 0x0D, 0x67, 0x0F, 0x47, 0x06, 0x16, 0x00, 0x8A, 0x12, 0x3A, 0x5B, 0x41, 0xDB, 0x11, 0xF4, 0x00, 0xAC, 0xCF, 0xDD, 0x96, 0xDB, 0x5F, 0xAA, 0xAE, 0x00, 0x6D, 0x3C, 0x2E, 0x7F, 0x8B, 0x72, 0xA3, 0x56, 0x00, 0x47, 0x7A, 0xF8, 0x43, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+#endif
\ No newline at end of file
diff --git a/makerom.c b/makerom.c
new file mode 100644
index 0000000..7ae172b
--- /dev/null
+++ b/makerom.c
@@ -0,0 +1,93 @@
+#include "lib.h"
+#include "ncch.h"
+#include "ncsd.h"
+#include "cia.h"
+
+int main(int argc, char *argv[])
+{
+ // Setting up user settings
+ user_settings *usrset = malloc(sizeof(user_settings));
+ if(usrset == NULL) {fprintf(stderr,"[!] MEM ERROR\n"); return -1;}
+ init_UserSettings(usrset);
+
+ int result;
+
+ // Parsing command args
+ result = ParseArgs(argc,argv,usrset);
+ if(result < 0) goto fail_finalise;
+
+ // Import RSF/DESC Settings if present
+ result = GetYamlSettings(usrset);
+ if(result < 0) goto fail_finalise;
+
+ // Setup Content 0
+ if(!usrset->IsBuildingNCCH0){ // Import Content 0
+ if(usrset->Content0IsNcch){
+ FILE *ncch0 = fopen(usrset->ContentPath[0],"rb");
+ if(!ncch0) {fprintf(stderr,"[MAKEROM ERROR] Failed to open Content 0: %s\n",usrset->ContentPath[0]); goto fail_finalise;}
+ fclose(ncch0);
+ usrset->Content0.size = GetFileSize_u64(usrset->ContentPath[0]);
+ usrset->Content0.buffer = malloc(usrset->Content0.size);
+ ncch0 = fopen(usrset->ContentPath[0],"rb");
+ ReadFile_64(usrset->Content0.buffer, usrset->Content0.size,0,ncch0);
+ fclose(ncch0);
+ }
+ else if(usrset->Content0IsSrl){
+ FILE *srl = fopen(usrset->SrlPath,"rb");
+ if(!srl) {fprintf(stderr,"[MAKEROM ERROR] Failed to open SRL: %s\n",usrset->SrlPath); goto fail_finalise;}
+ fclose(srl);
+ u64 size = GetFileSize_u64(usrset->SrlPath);
+ usrset->Content0.size = align_value(size,0x10);
+ usrset->Content0.buffer = malloc(usrset->Content0.size);
+ srl = fopen(usrset->SrlPath,"rb");
+ ReadFile_64(usrset->Content0.buffer,size,0,srl);
+ fclose(srl);
+ }
+ else if(usrset->Content0IsCci){
+ FILE *cci = fopen(usrset->CciPath,"rb");
+ if(!cci) {fprintf(stderr,"[MAKEROM ERROR] Failed to open CCI: %s\n",usrset->CciPath); goto fail_finalise;}
+ fclose(cci);
+ usrset->Content0.size = GetFileSize_u64(usrset->CciPath);
+ usrset->Content0.buffer = malloc(usrset->Content0.size);
+ cci = fopen(usrset->CciPath,"rb");
+ ReadFile_64(usrset->Content0.buffer, usrset->Content0.size,0,cci);
+ fclose(cci);
+ }
+ }
+ else{// Build Content 0
+ result = build_NCCH(usrset);
+ if(result < 0) {
+ fprintf(stderr,"[ERROR] %s generation failed\n",usrset->build_ncch_type == CXI? "CXI" : "CFA");
+ fprintf(stderr,"[RESULT] Failed to build outfile\n");
+ goto fail_finalise;
+ }
+ }
+ // Make CCI
+ if(usrset->out_format == CCI){
+ result = build_CCI(usrset);
+ if(result < 0) { fprintf(stderr,"[RESULT] Failed to build CCI\n"); goto fail_finalise; }
+ }
+ // Make CIA
+ else if(usrset->out_format == CIA){
+ result = build_CIA(usrset);
+ if(result < 0) { fprintf(stderr,"[RESULT] Failed to build CIA\n"); goto fail_finalise; }
+ }
+ // No Container Raw CXI/CFA
+ else if(usrset->out_format == CXI || usrset->out_format == CFA){
+ FILE *ncch_out = fopen(usrset->outfile,"wb");
+ if(!ncch_out) {
+ fprintf(stderr,"[ERROR] Failed to create '%s'\n",usrset->outfile);
+ fprintf(stderr,"[RESULT] Failed to build '%s'\n",usrset->out_format == CXI? "CXI" : "CFA");
+ result = FAILED_TO_CREATE_OUTFILE;
+ goto fail_finalise;
+ }
+ WriteBuffer(usrset->Content0.buffer,usrset->Content0.size,0,ncch_out);
+ fclose(ncch_out);
+ }
+
+ free_UserSettings(usrset);
+ return 0;
+fail_finalise:
+ free_UserSettings(usrset);
+ return result;
+}
\ No newline at end of file
diff --git a/makerom.h b/makerom.h
new file mode 100644
index 0000000..e69de29
diff --git a/ncch.c b/ncch.c
new file mode 100644
index 0000000..07627ff
--- /dev/null
+++ b/ncch.c
@@ -0,0 +1,1045 @@
+#include "lib.h"
+#include "ncch.h"
+#include "exheader.h"
+#include "elf.h"
+#include "exefs.h"
+#include "romfs.h"
+#include "titleid.h"
+#include "logo_data.h"
+
+// Private Prototypes
+int SignCFA(u8 *Signature, u8 *CFA_HDR, keys_struct *keys);
+int CheckCFASignature(u8 *Signature, u8 *CFA_HDR, keys_struct *keys);
+int SignCXI(u8 *Signature, u8 *CXI_HDR, u8 *PubK, u8 *PrivK);
+int CheckCXISignature(u8 *Signature, u8 *CXI_HDR, u8 *PubK);
+
+void init_NCCHSettings(ncch_settings *set);
+void free_NCCHSettings(ncch_settings *set);
+int get_NCCHSettings(ncch_settings *ncchset, user_settings *usrset);
+int SetBasicOptions(ncch_settings *ncchset, user_settings *usrset);
+int CreateInputFilePtrs(ncch_settings *ncchset, user_settings *usrset);
+int ImportNonCodeExeFsSections(ncch_settings *ncchset);
+int ImportLogo(ncch_settings *ncchset);
+
+int SetCommonHeaderBasicData(ncch_settings *ncchset, NCCH_Header *hdr);
+int SetCommonHeaderSectionData(ncch_settings *ncchset, NCCH_Header *hdr);
+bool IsValidProductCode(char *ProductCode, bool FreeProductCode);
+
+int BuildCommonHeader(ncch_settings *ncchset);
+int EncryptNCCHSections(ncch_settings *ncchset);
+int WriteNCCHSectionsToBuffer(ncch_settings *ncchset);
+
+// Code
+
+int SignCFA(u8 *Signature, u8 *CFA_HDR, keys_struct *keys)
+{
+ return ctr_sig(CFA_HDR,sizeof(NCCH_Header),Signature,keys->rsa.CFA_Pub,keys->rsa.CFA_Priv,RSA_2048_SHA256,CTR_RSA_SIGN);
+}
+
+int CheckCFASignature(u8 *Signature, u8 *CFA_HDR, keys_struct *keys)
+{
+ return ctr_sig(CFA_HDR,sizeof(NCCH_Header),Signature,keys->rsa.CFA_Pub,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY);
+}
+
+int SignCXI(u8 *Signature, u8 *CXI_HDR, u8 *PubK, u8 *PrivK)
+{
+ return ctr_sig(CXI_HDR,sizeof(NCCH_Header),Signature,PubK,PrivK,RSA_2048_SHA256,CTR_RSA_SIGN);
+}
+
+int CheckCXISignature(u8 *Signature, u8 *CXI_HDR, u8 *PubK)
+{
+ int result = ctr_sig(CXI_HDR,sizeof(NCCH_Header),Signature,PubK,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY);
+ return result;
+}
+
+// NCCH Build Functions
+
+int build_NCCH(user_settings *usrset)
+{
+ int result;
+
+ // Init Settings
+ ncch_settings *ncchset = malloc(sizeof(ncch_settings));
+ if(!ncchset) {fprintf(stderr,"[NCCH ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ init_NCCHSettings(ncchset);
+
+ // Get Settings
+ result = get_NCCHSettings(ncchset,usrset);
+ if(result) goto finish;
+
+ // Build ExeFs Code Section
+ result = BuildExeFsCode(ncchset);
+ if(result) goto finish;
+
+#ifdef ELF_DEBUG
+ FILE *code = fopen("code.bin","wb");
+ fwrite(ncchset->ExeFs_Sections.Code.buffer,ncchset->ExeFs_Sections.Code.size,1,code);
+ fclose(code);
+ u8 hash[0x20];
+ ctr_sha(ncchset->ExeFs_Sections.Code.buffer,ncchset->ExeFs_Sections.Code.size,hash,CTR_SHA_256);
+ printf("BSS Size: 0x%x\n",ncchset->CodeDetails.BSS_Size);
+ printf("Code Size: 0x%x\n",ncchset->ExeFs_Sections.Code.size);
+ memdump(stdout,"Code Hash: ",hash,0x20);
+#endif
+
+ // Build ExHeader
+ result = BuildExHeader(ncchset);
+ if(result) goto finish;
+
+
+ // Build ExeFs/RomFs
+ result = BuildExeFs(ncchset);
+ if(result) goto finish;
+ result = BuildRomFs(ncchset);
+ if(result) goto finish;
+
+ // Final Steps
+ result = BuildCommonHeader(ncchset);
+ if(result) goto finish;
+ result = EncryptNCCHSections(ncchset);
+ if(result) goto finish;
+ result = WriteNCCHSectionsToBuffer(ncchset);
+ if(result) goto finish;
+finish:
+ if(result) fprintf(stderr,"[NCCH ERROR] NCCH Build Process Failed\n");
+ free_NCCHSettings(ncchset);
+ return result;
+}
+
+void init_NCCHSettings(ncch_settings *set)
+{
+ memset(set,0,sizeof(ncch_settings));
+}
+
+void free_NCCHSettings(ncch_settings *set)
+{
+ if(set->CxiRsaKey.PrivK) free(set->CxiRsaKey.PrivK);
+ if(set->CxiRsaKey.PubK) free(set->CxiRsaKey.PubK);
+
+ if(set->ComponentFilePtrs.elf) fclose(set->ComponentFilePtrs.elf);
+ if(set->ComponentFilePtrs.banner) fclose(set->ComponentFilePtrs.banner);
+ if(set->ComponentFilePtrs.icon) fclose(set->ComponentFilePtrs.icon);
+ if(set->ComponentFilePtrs.logo) fclose(set->ComponentFilePtrs.logo);
+ if(set->ComponentFilePtrs.code) fclose(set->ComponentFilePtrs.code);
+ if(set->ComponentFilePtrs.exheader) fclose(set->ComponentFilePtrs.exheader);
+ if(set->ComponentFilePtrs.romfs) fclose(set->ComponentFilePtrs.romfs);
+ if(set->ComponentFilePtrs.plainregion) fclose(set->ComponentFilePtrs.plainregion);
+
+ if(set->ExeFs_Sections.Code.size) free(set->ExeFs_Sections.Code.buffer);
+ if(set->ExeFs_Sections.Banner.size) free(set->ExeFs_Sections.Banner.buffer);
+ if(set->ExeFs_Sections.Icon.size) free(set->ExeFs_Sections.Icon.buffer);
+
+ if(set->Sections.CommonHeader.size) free(set->Sections.CommonHeader.buffer);
+ if(set->Sections.ExHeader.size) free(set->Sections.ExHeader.buffer);
+ if(set->Sections.Logo.size) free(set->Sections.Logo.buffer);
+ if(set->Sections.PlainRegion.size) free(set->Sections.PlainRegion.buffer);
+ if(set->Sections.ExeFs.size) free(set->Sections.ExeFs.buffer);
+ if(set->Sections.RomFs.size) free(set->Sections.RomFs.buffer);
+
+ memset(set,0,sizeof(ncch_settings));
+
+ free(set);
+}
+
+int get_NCCHSettings(ncch_settings *ncchset, user_settings *usrset)
+{
+ int result = 0;
+ ncchset->out = &usrset->Content0;
+ ncchset->yaml_set = &usrset->yaml_set;
+ ncchset->keys = &usrset->keys;
+
+ result = SetBasicOptions(ncchset,usrset);
+ if(result) return result;
+ result = CreateInputFilePtrs(ncchset,usrset);
+ if(result) return result;
+ result = ImportNonCodeExeFsSections(ncchset);
+ if(result) return result;
+ result = ImportLogo(ncchset);
+ if(result) return result;
+
+
+ return 0;
+}
+
+int SetBasicOptions(ncch_settings *ncchset, user_settings *usrset)
+{
+ int result = 0;
+
+ /* Options */
+ ncchset->Options.MediaSize = 0x200;
+
+ ncchset->Options.IncludeExeFsLogo = usrset->include_exefs_logo;
+
+ if(usrset->yaml_set.DefaultSpec.Option.EnableCompress != -1) ncchset->Options.CompressCode = usrset->yaml_set.DefaultSpec.Option.EnableCompress;
+ else ncchset->Options.CompressCode = true;
+
+ if(usrset->yaml_set.DefaultSpec.Option.UseOnSD != -1) ncchset->Options.UseOnSD = usrset->yaml_set.DefaultSpec.Option.UseOnSD;
+ else ncchset->Options.UseOnSD = false;
+
+ if(usrset->yaml_set.DefaultSpec.Option.EnableCrypt != -1) ncchset->Options.Encrypt = usrset->yaml_set.DefaultSpec.Option.EnableCrypt;
+ else ncchset->Options.Encrypt = true;
+
+ if(usrset->yaml_set.DefaultSpec.Option.FreeProductCode != -1) ncchset->Options.FreeProductCode = usrset->yaml_set.DefaultSpec.Option.FreeProductCode;
+ else ncchset->Options.FreeProductCode = false;
+
+ ncchset->Options.IsCfa = (usrset->build_ncch_type == CFA);
+
+ ncchset->Options.IsBuildingCodeSection = (usrset->elf_path != NULL);
+
+ ncchset->Options.accessdesc = usrset->accessdesc;
+
+ ncchset->CxiRsaKey.PrivK = malloc(0x100);
+ ncchset->CxiRsaKey.PubK = malloc(0x100);
+
+ return result;
+}
+
+int CreateInputFilePtrs(ncch_settings *ncchset, user_settings *usrset)
+{
+ if(usrset->elf_path){
+ ncchset->ComponentFilePtrs.elf_size = GetFileSize_u64(usrset->elf_path);
+ ncchset->ComponentFilePtrs.elf = fopen(usrset->elf_path,"rb");
+ if(!ncchset->ComponentFilePtrs.elf){
+ fprintf(stderr,"[NCCH ERROR] Failed to open elf file '%s'\n",usrset->elf_path);
+ return FAILED_TO_IMPORT_FILE;
+ }
+ }
+ if(usrset->banner_path){
+ ncchset->ComponentFilePtrs.banner_size = GetFileSize_u64(usrset->banner_path);
+ ncchset->ComponentFilePtrs.banner = fopen(usrset->banner_path,"rb");
+ if(!ncchset->ComponentFilePtrs.banner){
+ fprintf(stderr,"[NCCH ERROR] Failed to open banner file '%s'\n",usrset->banner_path);
+ return FAILED_TO_IMPORT_FILE;
+ }
+ }
+ if(usrset->icon_path){
+ ncchset->ComponentFilePtrs.icon_size = GetFileSize_u64(usrset->icon_path);
+ ncchset->ComponentFilePtrs.icon = fopen(usrset->icon_path,"rb");
+ if(!ncchset->ComponentFilePtrs.icon){
+ fprintf(stderr,"[NCCH ERROR] Failed to open icon file '%s'\n",usrset->icon_path);
+ return FAILED_TO_IMPORT_FILE;
+ }
+ }
+ if(usrset->logo_path){
+ ncchset->ComponentFilePtrs.logo_size = GetFileSize_u64(usrset->logo_path);
+ ncchset->ComponentFilePtrs.logo = fopen(usrset->logo_path,"rb");
+ if(!ncchset->ComponentFilePtrs.logo){
+ fprintf(stderr,"[NCCH ERROR] Failed to open logo file '%s'\n",usrset->logo_path);
+ return FAILED_TO_IMPORT_FILE;
+ }
+ }
+
+ if(usrset->exefs_code_path){
+ ncchset->ComponentFilePtrs.code_size = GetFileSize_u64(usrset->exefs_code_path);
+ ncchset->ComponentFilePtrs.code = fopen(usrset->exefs_code_path,"rb");
+ if(!ncchset->ComponentFilePtrs.code){
+ fprintf(stderr,"[NCCH ERROR] Failed to open ExeFs Code file '%s'\n",usrset->exefs_code_path);
+ return FAILED_TO_IMPORT_FILE;
+ }
+ }
+ if(usrset->exheader_path){
+ ncchset->ComponentFilePtrs.exheader_size = GetFileSize_u64(usrset->exheader_path);
+ ncchset->ComponentFilePtrs.exheader = fopen(usrset->exheader_path,"rb");
+ if(!ncchset->ComponentFilePtrs.exheader){
+ fprintf(stderr,"[NCCH ERROR] Failed to open ExHeader file '%s'\n",usrset->exheader_path);
+ return FAILED_TO_IMPORT_FILE;
+ }
+ }
+ if(usrset->romfs_path){
+ ncchset->ComponentFilePtrs.romfs_size = GetFileSize_u64(usrset->romfs_path);
+ ncchset->ComponentFilePtrs.romfs = fopen(usrset->romfs_path,"rb");
+ if(!ncchset->ComponentFilePtrs.romfs){
+ fprintf(stderr,"[NCCH ERROR] Failed to open RomFs file '%s'\n",usrset->romfs_path);
+ return FAILED_TO_IMPORT_FILE;
+ }
+ }
+ if(usrset->plain_region_path){
+ ncchset->ComponentFilePtrs.plainregion_size = GetFileSize_u64(usrset->plain_region_path);
+ ncchset->ComponentFilePtrs.plainregion = fopen(usrset->plain_region_path,"rb");
+ if(!ncchset->ComponentFilePtrs.plainregion){
+ fprintf(stderr,"[NCCH ERROR] Failed to open PlainRegion file '%s'\n",usrset->plain_region_path);
+ return FAILED_TO_IMPORT_FILE;
+ }
+ }
+ return 0;
+}
+
+int ImportNonCodeExeFsSections(ncch_settings *ncchset)
+{
+ if(ncchset->ComponentFilePtrs.banner){
+ ncchset->ExeFs_Sections.Banner.size = ncchset->ComponentFilePtrs.banner_size;
+ ncchset->ExeFs_Sections.Banner.buffer = malloc(ncchset->ExeFs_Sections.Banner.size);
+ if(!ncchset->ExeFs_Sections.Banner.buffer) {fprintf(stderr,"[NCCH ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ ReadFile_64(ncchset->ExeFs_Sections.Banner.buffer,ncchset->ExeFs_Sections.Banner.size,0,ncchset->ComponentFilePtrs.banner);
+ }
+ if(ncchset->ComponentFilePtrs.icon){
+ ncchset->ExeFs_Sections.Icon.size = ncchset->ComponentFilePtrs.icon_size;
+ ncchset->ExeFs_Sections.Icon.buffer = malloc(ncchset->ExeFs_Sections.Icon.size);
+ if(!ncchset->ExeFs_Sections.Icon.buffer) {fprintf(stderr,"[NCCH ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ ReadFile_64(ncchset->ExeFs_Sections.Icon.buffer,ncchset->ExeFs_Sections.Icon.size,0,ncchset->ComponentFilePtrs.icon);
+ }
+ return 0;
+}
+
+int ImportLogo(ncch_settings *ncchset)
+{
+ if(ncchset->ComponentFilePtrs.logo){
+ ncchset->Sections.Logo.size = ncchset->ComponentFilePtrs.logo_size;
+ ncchset->Sections.Logo.buffer = malloc(ncchset->Sections.Logo.size);
+ if(!ncchset->Sections.Logo.buffer) {fprintf(stderr,"[NCCH ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ ReadFile_64(ncchset->Sections.Logo.buffer,ncchset->Sections.Logo.size,0,ncchset->ComponentFilePtrs.logo);
+ }
+ else if(ncchset->yaml_set->DefaultSpec.BasicInfo.Logo){
+ if(strcasecmp(ncchset->yaml_set->DefaultSpec.BasicInfo.Logo,"nintendo") == 0){
+ ncchset->Sections.Logo.size = 0x2000;
+ ncchset->Sections.Logo.buffer = malloc(ncchset->Sections.Logo.size);
+ if(!ncchset->Sections.Logo.buffer) {fprintf(stderr,"[NCCH ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ memcpy(ncchset->Sections.Logo.buffer,Nintendo_LZ,0x2000);
+ }
+ else if(strcasecmp(ncchset->yaml_set->DefaultSpec.BasicInfo.Logo,"licensed") == 0){
+ ncchset->Sections.Logo.size = 0x2000;
+ ncchset->Sections.Logo.buffer = malloc(ncchset->Sections.Logo.size);
+ if(!ncchset->Sections.Logo.buffer) {fprintf(stderr,"[NCCH ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ memcpy(ncchset->Sections.Logo.buffer,Nintendo_LicensedBy_LZ,0x2000);
+ }
+ else if(strcasecmp(ncchset->yaml_set->DefaultSpec.BasicInfo.Logo,"distributed") == 0){
+ ncchset->Sections.Logo.size = 0x2000;
+ ncchset->Sections.Logo.buffer = malloc(ncchset->Sections.Logo.size);
+ if(!ncchset->Sections.Logo.buffer) {fprintf(stderr,"[NCCH ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ memcpy(ncchset->Sections.Logo.buffer,Nintendo_DistributedBy_LZ,0x2000);
+ }
+ else if(strcasecmp(ncchset->yaml_set->DefaultSpec.BasicInfo.Logo,"ique") == 0){
+ ncchset->Sections.Logo.size = 0x2000;
+ ncchset->Sections.Logo.buffer = malloc(ncchset->Sections.Logo.size);
+ if(!ncchset->Sections.Logo.buffer) {fprintf(stderr,"[NCCH ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ memcpy(ncchset->Sections.Logo.buffer,iQue_with_ISBN_LZ,0x2000);
+ }
+ else if(strcasecmp(ncchset->yaml_set->DefaultSpec.BasicInfo.Logo,"ique_without_isbn") == 0){
+ ncchset->Sections.Logo.size = 0x2000;
+ ncchset->Sections.Logo.buffer = malloc(ncchset->Sections.Logo.size);
+ if(!ncchset->Sections.Logo.buffer) {fprintf(stderr,"[NCCH ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ memcpy(ncchset->Sections.Logo.buffer,iQue_without_ISBN_LZ,0x2000);
+ }
+ else if(strcasecmp(ncchset->yaml_set->DefaultSpec.BasicInfo.Logo,"none") != 0){
+ fprintf(stderr,"[NCCH ERROR] Invalid logo name\n");
+ return NCCH_BAD_YAML_SET;
+ }
+ }
+ return 0;
+}
+
+int SetCommonHeaderBasicData(ncch_settings *ncchset, NCCH_Header *hdr)
+{
+ /* NCCH Format Version */
+ u16_to_u8(hdr->version,0x2,LE);
+
+ /* Setting ProgramId/TitleId */
+ u64 ProgramId = 0;
+ int result = GetProgramID(&ProgramId,ncchset->yaml_set,false);
+ if(result) return result;
+
+ u64_to_u8(hdr->program_id,ProgramId,LE);
+ u64_to_u8(hdr->title_id,ProgramId,LE);
+
+ /* Get Product Code and Maker Code */
+ if(ncchset->yaml_set->DefaultSpec.BasicInfo.ProductCode){
+ if(!IsValidProductCode((char*)ncchset->yaml_set->DefaultSpec.BasicInfo.ProductCode,ncchset->Options.FreeProductCode)){
+ fprintf(stderr,"[NCCH ERROR] Invalid Product Code\n");
+ return NCCH_BAD_YAML_SET;
+ }
+ memcpy(hdr->product_code,ncchset->yaml_set->DefaultSpec.BasicInfo.ProductCode,strlen((char*)ncchset->yaml_set->DefaultSpec.BasicInfo.ProductCode));
+ }
+ else memcpy(hdr->product_code,"CTR-P-CTAP",10);
+
+ if(ncchset->yaml_set->DefaultSpec.BasicInfo.CompanyCode){
+ if(strlen((char*)ncchset->yaml_set->DefaultSpec.BasicInfo.CompanyCode) != 2){
+ fprintf(stderr,"[NCCH ERROR] Company code length must be 2\n");
+ return NCCH_BAD_YAML_SET;
+ }
+ memcpy(hdr->maker_code,ncchset->yaml_set->DefaultSpec.BasicInfo.CompanyCode,2);
+ }
+ else memcpy(hdr->maker_code,"00",2);
+
+ /* Set ContentUnitSize */
+ hdr->flags[ContentUnitSize] = 0;
+
+ /* Setting ContentPlatform */
+ if(ncchset->yaml_set->DefaultSpec.TitleInfo.Platform){
+ if(strcasecmp(ncchset->yaml_set->DefaultSpec.TitleInfo.Platform,"ctr") == 0) hdr->flags[ContentPlatform] = 1;
+ else{
+ fprintf(stderr,"[NCCH ERROR] Invalid Platform: %s\n",ncchset->yaml_set->DefaultSpec.TitleInfo.Platform);
+ return NCCH_BAD_YAML_SET;
+ }
+ }
+ else
+ hdr->flags[ContentPlatform] = 1; // CTR
+
+ /* Setting OtherFlag */
+ hdr->flags[OtherFlag] = FixedCryptoKey;
+ if(!ncchset->Options.Encrypt) hdr->flags[OtherFlag] |= NoCrypto;
+ if(!ncchset->Sections.RomFs.size) hdr->flags[OtherFlag] |= NoMountRomFs;
+
+
+ /* Setting ContentType */
+ hdr->flags[ContentType] = 0;
+ if(ncchset->Sections.RomFs.size) hdr->flags[ContentType] |= RomFS;
+ if(ncchset->Sections.ExeFs.size) hdr->flags[ContentType] |= ExeFS;
+ if(ncchset->yaml_set->DefaultSpec.BasicInfo.ContentType){
+ if(strcmp(ncchset->yaml_set->DefaultSpec.BasicInfo.ContentType,"Application") == 0) hdr->flags[ContentType] |= 0;
+ else if(strcmp(ncchset->yaml_set->DefaultSpec.BasicInfo.ContentType,"SystemUpdate") == 0) hdr->flags[ContentType] |= SystemUpdate;
+ else if(strcmp(ncchset->yaml_set->DefaultSpec.BasicInfo.ContentType,"Manual") == 0) hdr->flags[ContentType] |= Manual;
+ else if(strcmp(ncchset->yaml_set->DefaultSpec.BasicInfo.ContentType,"Child") == 0) hdr->flags[ContentType] |= Child;
+ else if(strcmp(ncchset->yaml_set->DefaultSpec.BasicInfo.ContentType,"Trial") == 0) hdr->flags[ContentType] |= Trial;
+ else{
+ fprintf(stderr,"[NCCH ERROR] Invalid ContentType '%s'\n",ncchset->yaml_set->DefaultSpec.BasicInfo.ContentType);
+ return NCCH_BAD_YAML_SET;
+ }
+ }
+
+ return 0;
+}
+
+int SetCommonHeaderSectionData(ncch_settings *ncchset, NCCH_Header *hdr)
+{
+ /* Set Sizes/Hashes to Hdr */
+ u32 ExHeaderSize = (u32) ncchset->Sections.ExHeader.size - 0x400;
+ u32 LogoSize = (u32) (ncchset->Sections.Logo.size/ncchset->Options.MediaSize);
+ u32 PlainRegionSize = (u32) (ncchset->Sections.PlainRegion.size/ncchset->Options.MediaSize);
+ u32 ExeFsSize = (u32) (ncchset->Sections.ExeFs.size/ncchset->Options.MediaSize);
+ u32 ExeFsHashSize = (u32) ExeFsSize? ncchset->Options.MediaSize/ncchset->Options.MediaSize : 0;
+ u32 RomFsSize = (u32) (ncchset->Sections.RomFs.size/ncchset->Options.MediaSize);
+ u32 RomFsHashSize = (u32) RomFsSize? ncchset->Options.MediaSize/ncchset->Options.MediaSize : 0;
+
+ u32_to_u8(hdr->extended_header_size,ExHeaderSize,LE);
+ if(ExHeaderSize) ctr_sha(ncchset->Sections.ExHeader.buffer,ExHeaderSize,hdr->extended_header_sha_256_hash,CTR_SHA_256);
+
+ u32_to_u8(hdr->logo_region_size,LogoSize,LE);
+ if(LogoSize) ctr_sha(ncchset->Sections.Logo.buffer,ncchset->Sections.Logo.size,hdr->logo_sha_256_hash,CTR_SHA_256);
+
+ u32_to_u8(hdr->plain_region_size,PlainRegionSize,LE);
+
+ u32_to_u8(hdr->exefs_size,ExeFsSize,LE);
+ u32_to_u8(hdr->exefs_hash_size,ExeFsHashSize,LE);
+ if(ExeFsSize) ctr_sha(ncchset->Sections.ExeFs.buffer,ncchset->Options.MediaSize,hdr->exefs_sha_256_hash,CTR_SHA_256);
+
+ u32_to_u8(hdr->romfs_size,RomFsSize,LE);
+ u32_to_u8(hdr->romfs_hash_size,RomFsHashSize,LE);
+ if(RomFsSize) ctr_sha(ncchset->Sections.RomFs.buffer,ncchset->Options.MediaSize,hdr->romfs_sha_256_hash,CTR_SHA_256);
+
+
+ /* Get Section Offsets */
+ u32 size = 1;
+ if (ExHeaderSize)
+ size += 4;
+
+ if (LogoSize){
+ u32_to_u8(hdr->logo_region_offset,size,LE);
+ ncchset->Sections.LogoOffset = size*ncchset->Options.MediaSize;
+ size += LogoSize;
+ }
+
+ if(PlainRegionSize){
+ u32_to_u8(hdr->plain_region_offset,size,LE);
+ ncchset->Sections.PlainRegionOffset = size*ncchset->Options.MediaSize;
+ size += PlainRegionSize;
+ }
+
+ if (ExeFsSize){
+ u32_to_u8(hdr->exefs_offset,size,LE);
+ ncchset->Sections.ExeFsOffset = size*ncchset->Options.MediaSize;
+ size += ExeFsSize;
+ }
+
+ if (RomFsSize){
+ u32_to_u8(hdr->romfs_offset,size,LE);
+ ncchset->Sections.RomFsOffset = size*ncchset->Options.MediaSize;
+ size += RomFsSize;
+ }
+
+ u32_to_u8(hdr->content_size,size,LE);
+
+ ncchset->Sections.TotalContentSize = size * ncchset->Options.MediaSize;
+
+ return 0;
+}
+
+bool IsValidProductCode(char *ProductCode, bool FreeProductCode)
+{
+ if(strlen(ProductCode) > 16) return false;
+
+ if(FreeProductCode)
+ return true;
+
+ if(strlen(ProductCode) < 10) return false;
+ if(strncmp(ProductCode,"CTR-",4) != 0) return false;
+ if(ProductCode[5] != '-') return false;
+ if(!isdigit(ProductCode[4]) && !isupper(ProductCode[4])) return false;
+ for(int i = 6; i < 10; i++){
+ if(!isdigit(ProductCode[i]) && !isupper(ProductCode[i])) return false;
+ }
+
+ return true;
+}
+
+int BuildCommonHeader(ncch_settings *ncchset)
+{
+ int result = 0;
+
+ // Initialising Header
+ ncchset->Sections.CommonHeader.size = 0x100 + sizeof(NCCH_Header);
+ ncchset->Sections.CommonHeader.buffer = malloc(ncchset->Sections.CommonHeader.size);
+ if(!ncchset->Sections.CommonHeader.buffer) { fprintf(stderr,"[NCCH ERROR] MEM ERROR\n"); return MEM_ERROR; }
+ memset(ncchset->Sections.CommonHeader.buffer,0,ncchset->Sections.CommonHeader.size);
+
+ // Creating Ptrs
+ u8 *sig = ncchset->Sections.CommonHeader.buffer;
+ NCCH_Header *hdr = (NCCH_Header*)(ncchset->Sections.CommonHeader.buffer+0x100);
+
+ // Setting Data in Hdr
+ memcpy(hdr->magic,"NCCH",4);
+
+ result = SetCommonHeaderBasicData(ncchset,hdr);
+ if(result) return result;
+
+ result = SetCommonHeaderSectionData(ncchset,hdr);
+ if(result) return result;
+
+
+ // Signing Hdr
+ int sig_result = Good;
+ if(ncchset->Options.IsCfa) sig_result = SignCFA(sig,(u8*)hdr,ncchset->keys);
+ else sig_result = SignCXI(sig,(u8*)hdr,ncchset->CxiRsaKey.PubK,ncchset->CxiRsaKey.PrivK);
+ if(sig_result != Good){
+ fprintf(stderr,"[NCCH ERROR] Failed to sign %s header\n",ncchset->Options.IsCfa ? "CFA" : "CXI");
+ return sig_result;
+ }
+
+ return 0;
+}
+
+int EncryptNCCHSections(ncch_settings *ncchset)
+{
+ if(!ncchset->Options.Encrypt) return 0;
+
+ /* Getting NCCH_STRUCT */
+ NCCH_Header *hdr = GetNCCH_CommonHDR(NULL,NULL,ncchset->Sections.CommonHeader.buffer);
+ NCCH_STRUCT *ncch = malloc(sizeof(NCCH_STRUCT));
+ if(!ncch) { fprintf(stderr,"[NCCH ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ memset(ncch,0,sizeof(NCCH_STRUCT));
+ GetCXIStruct(ncch,hdr);
+
+ u8 *ncch_key = GetNCCHKey(hdr,ncchset->keys);
+
+ if(ncchset->Sections.ExHeader.size)
+ CryptNCCHSection(ncchset->Sections.ExHeader.buffer,ncchset->Sections.ExHeader.size,0,ncch,ncch_key,ncch_ExHeader);
+
+ if(ncchset->Sections.ExeFs.size)
+ CryptNCCHSection(ncchset->Sections.ExeFs.buffer,ncchset->Sections.ExeFs.size,0,ncch,ncch_key,ncch_exefs);
+
+ if(ncchset->Sections.RomFs.size)
+ CryptNCCHSection(ncchset->Sections.RomFs.buffer,ncchset->Sections.RomFs.size,0,ncch,ncch_key,ncch_romfs);
+
+ return 0;
+}
+
+int WriteNCCHSectionsToBuffer(ncch_settings *ncchset)
+{
+ /* Allocating Memory for NCCH, and clearing */
+ ncchset->out->size = ncchset->Sections.TotalContentSize;
+ ncchset->out->buffer = malloc(ncchset->out->size);
+ if(!ncchset->out->buffer) { fprintf(stderr,"[NCCH ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ memset(ncchset->out->buffer,0,ncchset->out->size);
+
+ /* Copy Header+Sig */
+ memcpy(ncchset->out->buffer,ncchset->Sections.CommonHeader.buffer,ncchset->Sections.CommonHeader.size);
+
+ /* Copy Exheader+AccessDesc */
+ if(ncchset->Sections.ExHeader.size)
+ memcpy(ncchset->out->buffer+0x200,ncchset->Sections.ExHeader.buffer,ncchset->Sections.ExHeader.size);
+
+ /* Copy Logo */
+ if(ncchset->Sections.Logo.size)
+ memcpy(ncchset->out->buffer+ncchset->Sections.LogoOffset,ncchset->Sections.Logo.buffer,ncchset->Sections.Logo.size);
+
+ /* Copy PlainRegion */
+ if(ncchset->Sections.PlainRegion.size)
+ memcpy(ncchset->out->buffer+ncchset->Sections.PlainRegionOffset,ncchset->Sections.PlainRegion.buffer,ncchset->Sections.PlainRegion.size);
+
+ /* Copy ExeFs */
+ if(ncchset->Sections.ExeFs.size)
+ memcpy(ncchset->out->buffer+ncchset->Sections.ExeFsOffset,ncchset->Sections.ExeFs.buffer,ncchset->Sections.ExeFs.size);
+
+ /* Copy RomFs */
+ if(ncchset->Sections.RomFs.size)
+ memcpy(ncchset->out->buffer+ncchset->Sections.RomFsOffset,ncchset->Sections.RomFs.buffer,ncchset->Sections.RomFs.size);
+
+ return 0;
+}
+
+// NCCH Read Functions
+
+int VerifyNCCH(u8 *ncch, keys_struct *keys, bool SuppressOutput)
+{
+ // Setup
+ u8 Hash[0x20];
+ u8 *hdr_sig = ncch;
+ NCCH_Header* hdr = GetNCCH_CommonHDR(NULL,NULL,ncch);
+
+ NCCH_STRUCT *ncch_ctx = malloc(sizeof(NCCH_STRUCT));
+ if(!ncch_ctx){ fprintf(stderr,"[NCCH ERROR] MEM ERROR\n"); return MEM_ERROR; }
+ memset(ncch_ctx,0x0,sizeof(NCCH_STRUCT));
+ GetCXIStruct(ncch_ctx,hdr);
+
+ if(IsCfa(hdr)){
+ if(CheckCFASignature(hdr_sig,(u8*)hdr,keys) != Good){
+#ifdef RETAIL_FSIGN
+ if(!SuppressOutput) fprintf(stderr,"[NCCH WARNING] CFA Sigcheck Failed\n");
+#else
+ if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] CFA Sigcheck Failed\n");
+ free(ncch_ctx);
+ return NCCH_HDR_SIG_BAD;
+#endif
+ }
+ if(!ncch_ctx->romfs_size){
+ if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] CFA is corrupt\n");
+ free(ncch_ctx);
+ return NO_ROMFS_IN_CFA;
+ }
+ u8 *RomFs = malloc(ncch_ctx->romfs_hash_src_size);
+ if(!RomFs){
+ fprintf(stderr,"[NCCH ERROR] MEM ERROR\n");
+ free(ncch_ctx);
+ return MEM_ERROR;
+ }
+ int ret = GetNCCHSection(RomFs,ncch_ctx->romfs_hash_src_size,0,ncch,ncch_ctx,keys,ncch_romfs);
+ if(ret != 0 && ret != UNABLE_TO_LOAD_NCCH_KEY){
+ if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] CFA is corrupt\n");
+ free(ncch_ctx);
+ free(RomFs);
+ return CXI_CORRUPT;
+ }
+ else if(ret == UNABLE_TO_LOAD_NCCH_KEY){
+ if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] Failed to load ncch aes key.\n");
+ free(ncch_ctx);
+ free(RomFs);
+ return UNABLE_TO_LOAD_NCCH_KEY;
+ }
+
+ ctr_sha(RomFs,ncch_ctx->romfs_hash_src_size,Hash,CTR_SHA_256);
+ free(RomFs);
+ if(memcmp(Hash,hdr->romfs_sha_256_hash,0x20) != 0){
+ if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] RomFs Hashcheck Failed\n");
+ free(ncch_ctx);
+ return ExeFs_Hashfail;
+ }
+ }
+ else{ // IsCxi
+ // Checking for necessary sections
+ if(!ncch_ctx->exheader_size){
+ if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] CXI is corrupt\n");
+ free(ncch_ctx);
+ return NO_EXHEADER_IN_CXI;
+ }
+ if(!ncch_ctx->exefs_size){
+ if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] CXI is corrupt\n");
+ free(ncch_ctx);
+ return NO_EXEFS_IN_CXI;
+ }
+ // Get ExHeader
+ ExtendedHeader_Struct *ExHeader = malloc(ncch_ctx->exheader_size);
+ if(!ExHeader){
+ fprintf(stderr,"[NCCH ERROR] MEM ERROR\n");
+ free(ncch_ctx);
+ return MEM_ERROR;
+ }
+ int ret = GetNCCHSection((u8*)ExHeader,ncch_ctx->exheader_size,0,ncch,ncch_ctx,keys,ncch_ExHeader);
+ if(ret != 0 && ret != UNABLE_TO_LOAD_NCCH_KEY){
+ if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] CXI is corrupt\n");
+ free(ncch_ctx);
+ free(ExHeader);
+ return CXI_CORRUPT;
+ }
+ else if(ret == UNABLE_TO_LOAD_NCCH_KEY){
+ if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] Failed to load ncch aes key.\n");
+ free(ncch_ctx);
+ free(ExHeader);
+ return UNABLE_TO_LOAD_NCCH_KEY;
+ }
+
+ // Checking Exheader Hash to see if decryption was sucessful
+ ctr_sha(ExHeader,0x400,Hash,CTR_SHA_256);
+ if(memcmp(Hash,hdr->extended_header_sha_256_hash,0x20) != 0){
+ if(!SuppressOutput) {
+ fprintf(stderr,"[NCCH ERROR] ExHeader Hashcheck Failed\n");
+ fprintf(stderr,"[NCCH ERROR] CXI is corrupt\n");
+ }
+ free(ncch_ctx);
+ free(ExHeader);
+ return ExHeader_Hashfail;
+ }
+
+ // Checking RSA Sigs
+ u8 *hdr_pubk = GetNcchHdrPubKey_frm_exhdr(ExHeader);
+
+ if(CheckAccessDescSignature(ExHeader,keys) != 0){
+#ifdef RETAIL_FSIGN
+ if(!SuppressOutput) fprintf(stderr,"[NCCH WARNING] AccessDesc Sigcheck Failed\n");
+#else
+ if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] AccessDesc Sigcheck Failed\n");
+ free(ncch_ctx);
+ free(ExHeader);
+ return ACCESSDESC_SIG_BAD;
+#endif
+ }
+ if(CheckCXISignature(hdr_sig,(u8*)hdr,hdr_pubk) != 0){
+ if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] CXI Header Sigcheck Failed\n");
+ free(ncch_ctx);
+ free(ExHeader);
+ return NCCH_HDR_SIG_BAD;
+ }
+ free(ExHeader);
+
+ // It is assumed by this point, everything is fine
+
+ /* Checking ExeFs Hash */
+ u8 *ExeFs = malloc(ncch_ctx->exefs_hash_src_size);
+ if(!ExeFs){
+ fprintf(stderr,"[NCCH ERROR] MEM ERROR\n");
+ free(ncch_ctx);
+ return MEM_ERROR;
+ }
+ GetNCCHSection(ExeFs,ncch_ctx->exefs_hash_src_size,0,ncch,ncch_ctx,keys,ncch_exefs);
+ ctr_sha(ExeFs,ncch_ctx->exefs_hash_src_size,Hash,CTR_SHA_256);
+ free(ExeFs);
+ if(memcmp(Hash,hdr->exefs_sha_256_hash,0x20) != 0){
+ if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] ExeFs Hashcheck Failed\n");
+ free(ncch_ctx);
+ return ExeFs_Hashfail;
+ }
+
+ /* Checking RomFs hash, if present */
+ if(ncch_ctx->romfs_size){
+ u8 *RomFs = malloc(ncch_ctx->romfs_hash_src_size);
+ if(!RomFs){
+ fprintf(stderr,"[NCCH ERROR] MEM ERROR\n");
+ free(ncch_ctx);
+ return MEM_ERROR;
+ }
+ GetNCCHSection(RomFs,ncch_ctx->romfs_hash_src_size,0,ncch,ncch_ctx,keys,ncch_romfs);
+ ctr_sha(RomFs,ncch_ctx->romfs_hash_src_size,Hash,CTR_SHA_256);
+ free(RomFs);
+ if(memcmp(Hash,hdr->romfs_sha_256_hash,0x20) != 0){
+ if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] RomFs Hashcheck Failed\n");
+ free(ncch_ctx);
+ return ExeFs_Hashfail;
+ }
+ }
+
+ /* Checking the Logo Hash, if present */
+ if(ncch_ctx->logo_size){
+ u8 *logo = (ncch+ncch_ctx->logo_offset);
+ ctr_sha(logo,ncch_ctx->logo_size,Hash,CTR_SHA_256);
+ if(memcmp(Hash,hdr->logo_sha_256_hash,0x20) != 0){
+ if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] Logo Hashcheck Failed\n");
+ free(ncch_ctx);
+ return Logo_Hashfail;
+ }
+ }
+ }
+
+ free(ncch_ctx);
+ return 0;
+}
+
+
+u8* RetargetNCCH(FILE *fp, u64 size, u8 *TitleId, u8 *ProgramId, keys_struct *keys)
+{
+ u8 *ncch = malloc(size);
+ if(!ncch){
+ fprintf(stderr,"[NCCH ERROR] MEM ERROR\n");
+ return NULL;
+ }
+ ReadFile_64(ncch,size,0,fp); // Importing
+
+ if(!IsNCCH(NULL,ncch)){
+ free(ncch);
+ return NULL;
+ }
+
+ NCCH_Header *hdr = NULL;
+ hdr = GetNCCH_CommonHDR(NULL,NULL,ncch);
+
+ if(!IsCfa(hdr)){
+ fprintf(stderr,"[NCCH ERROR] CXI's ID cannot be modified\n"); // Not yet yet, requires AccessDesc Privk, may implement anyway later
+ free(ncch);
+ return NULL;
+ }
+
+ if((memcmp(TitleId,hdr->title_id,8) == 0) && (memcmp(ProgramId,hdr->program_id,8) == 0))
+ return ncch;// if no modification is required don't do anything
+
+ if(memcmp(TitleId,hdr->title_id,8) == 0){ // If TitleID Same, no crypto required, just resign.
+ memcpy(hdr->program_id,ProgramId,8);
+ SignCFA(ncch,(u8*)hdr,keys);
+ return ncch;
+ }
+
+ ncch_key_type keytype = GetNCCHKeyType(hdr);
+ u8 *key = NULL;
+
+ if(keytype == KeyIsUnFixed || keytype == KeyIsUnFixed2){
+ fprintf(stderr,"[NCCH ERROR] Unknown aes key\n");
+ free(ncch);
+ return NULL;
+ }
+
+
+ NCCH_STRUCT ncch_struct;
+ if(keytype != NoKey){ //Decrypting if necessary
+ GetCXIStruct(&ncch_struct,hdr);
+ u8 *romfs = (ncch+ncch_struct.romfs_offset);
+ key = GetNCCHKey(hdr,keys);
+ if(key == NULL){
+ fprintf(stderr,"[NCCH ERROR] Failed to load ncch aes key\n");
+ free(ncch);
+ return NULL;
+ }
+ CryptNCCHSection(romfs,ncch_struct.romfs_size,0,&ncch_struct,key,ncch_romfs);
+ }
+
+
+ memcpy(hdr->title_id,TitleId,8);
+ memcpy(hdr->program_id,ProgramId,8);
+
+ //Checking New Fixed Key Type
+ keytype = GetNCCHKeyType(hdr);
+
+ if(keytype != NoKey){ // Re-encrypting if necessary
+ GetCXIStruct(&ncch_struct,hdr);
+ u8 *romfs = (ncch+ncch_struct.romfs_offset);
+ key = GetNCCHKey(hdr,keys);
+ if(key == NULL){
+ fprintf(stderr,"[NCCH ERROR] Failed to load ncch aes key\n");
+ free(ncch);
+ return NULL;
+ }
+ CryptNCCHSection(romfs,ncch_struct.romfs_size,0,&ncch_struct,key,ncch_romfs);
+ }
+
+ SignCFA(ncch,(u8*)hdr,keys);
+
+ return ncch;
+}
+
+
+NCCH_Header* GetNCCH_CommonHDR(void *out, FILE *fp, u8 *buf)
+{
+ if(!fp && !buf) return NULL;
+ if(fp){
+ if(!out) return NULL;
+ ReadFile_64(out,0x100,0x100,fp);
+ return (NCCH_Header*)out;
+ }
+ else{
+ return (NCCH_Header*)(buf+0x100);
+ }
+}
+
+
+bool IsNCCH(FILE *fp, u8 *buf)
+{
+ if(!fp && !buf) return false;
+ NCCH_Header *ncchHDR = NULL;
+ bool result;
+ if(fp) {
+ ncchHDR = malloc(sizeof(NCCH_Header));
+ GetNCCH_CommonHDR(ncchHDR,fp,NULL);
+ result = (memcmp(ncchHDR->magic,"NCCH",4) == 0);
+ free(ncchHDR);
+ }
+ else {
+ ncchHDR = GetNCCH_CommonHDR(ncchHDR,NULL,buf);
+ result = (memcmp(ncchHDR->magic,"NCCH",4) == 0);
+ }
+ return result;
+}
+
+bool IsCfa(NCCH_Header* hdr)
+{
+ return (((hdr->flags[ContentType] & RomFS) == RomFS) && ((hdr->flags[ContentType] & ExeFS) != ExeFS));
+}
+
+u32 GetNCCH_MediaUnitSize(NCCH_Header* hdr)
+{
+ return 0x200*pow(2,hdr->flags[ContentUnitSize]);
+}
+
+u32 GetNCCH_MediaSize(NCCH_Header* hdr)
+{
+ return u8_to_u32(hdr->content_size,LE);
+}
+
+ncch_key_type GetNCCHKeyType(NCCH_Header* hdr)
+{
+ // Non-Secure Key Options
+ if((hdr->flags[OtherFlag] & NoCrypto) == NoCrypto) return NoKey;
+ if((hdr->flags[OtherFlag] & FixedCryptoKey) == FixedCryptoKey){
+ if((hdr->program_id[3] & 0x10) == 0x10) return KeyIsSystemFixed;
+ else return KeyIsNormalFixed;
+ }
+
+ // Secure Key Options
+ if(hdr->flags[SecureCrypto2] == 1) return KeyIsUnFixed2;
+ return KeyIsUnFixed;
+}
+
+u8* GetNCCHKey(NCCH_Header* hdr, keys_struct *keys)
+{
+ ncch_key_type keytype = GetNCCHKeyType(hdr);
+ switch(keytype){
+ case NoKey: return NULL;
+ case KeyIsNormalFixed: return keys->aes.NormalKey;
+ case KeyIsSystemFixed:
+ if(!keys->aes.SystemFixedKey) fprintf(stderr,"[NCCH WARNING] Unable to load SystemFixed Key\n");
+ return keys->aes.SystemFixedKey;
+ case KeyIsUnFixed:
+ if(!keys->aes.UnFixedKey) fprintf(stderr,"[NCCH WARNING] Unable to load UnFixed Key\n");
+ return keys->aes.UnFixedKey;
+ case KeyIsUnFixed2:
+ fprintf(stderr,"[NCCH WARNING] Crypto method (Secure2) not supported yet\n");
+ return NULL;
+ }
+ return NULL;
+}
+
+int GetNCCHSection(u8 *dest, u64 dest_max_size, u64 src_pos, u8 *ncch, NCCH_STRUCT *ncch_ctx, keys_struct *keys, ncch_section section)
+{
+ if(!ncch) return MEM_ERROR;
+ u8 *key = NULL;
+ NCCH_Header* hdr = GetNCCH_CommonHDR(NULL,NULL,ncch);
+ ncch_key_type keytype = GetNCCHKeyType(hdr);
+
+ if(keytype != NoKey && (section == ncch_ExHeader || section == ncch_exefs || section == ncch_romfs)){
+ key = GetNCCHKey(hdr,keys);
+ if(key == NULL){
+ //fprintf(stderr,"[NCCH ERROR] Failed to load ncch aes key.\n");
+ return UNABLE_TO_LOAD_NCCH_KEY;
+ }
+ }
+ //printf("detecting section type\n");
+ u64 offset = 0;
+ u64 size = 0;
+ switch(section){
+ case ncch_ExHeader:
+ offset = ncch_ctx->exheader_offset;
+ size = ncch_ctx->exheader_size;
+ break;
+ case ncch_Logo:
+ offset = ncch_ctx->logo_offset;
+ size = ncch_ctx->logo_size;
+ break;
+ case ncch_PlainRegion:
+ offset = ncch_ctx->plain_region_offset;
+ size = ncch_ctx->plain_region_size;
+ break;
+ case ncch_exefs:
+ offset = ncch_ctx->exefs_offset;
+ size = ncch_ctx->exefs_size;
+ break;
+ case ncch_romfs:
+ offset = ncch_ctx->romfs_offset;
+ size = ncch_ctx->romfs_size;
+ break;
+ }
+ if(!offset || !size) return NCCH_SECTION_NOT_EXIST;
+
+ if(src_pos > size) return DATA_POS_DNE;
+
+ size = min_u64(size-src_pos,dest_max_size);
+
+ //printf("Copying data\n");
+ u8 *section_pos = (ncch + offset + src_pos);
+ memcpy(dest,section_pos,size);
+
+ //printf("decrypting if needed\n");
+ if(keytype != NoKey && (section == ncch_ExHeader || section == ncch_exefs || section == ncch_romfs)){ // Decrypt
+ //memdump(stdout,"Key: ",key,16);
+ CryptNCCHSection(dest,size,src_pos,ncch_ctx,key,section);
+ //printf("no cigar\n");
+ }
+
+ return 0;
+}
+
+int GetCXIStruct(NCCH_STRUCT *ctx, NCCH_Header *header)
+{
+ memcpy(ctx->titleID,header->title_id,8);
+ memcpy(ctx->programID,header->program_id,8);
+
+
+ u32 media_unit = GetNCCH_MediaUnitSize(header);
+
+ ctx->version = u8_to_u16(header->version,LE);
+ if(!IsCfa(header)){
+ ctx->exheader_offset = 0x200;
+ ctx->exheader_size = u8_to_u32(header->extended_header_size,LE) + 0x400;
+ ctx->logo_offset = (u64)(u8_to_u32(header->logo_region_offset,LE)*media_unit);
+ ctx->logo_size = (u64)(u8_to_u32(header->logo_region_size,LE)*media_unit);
+ ctx->plain_region_offset = (u64)(u8_to_u32(header->plain_region_offset,LE)*media_unit);
+ ctx->plain_region_size = (u64)(u8_to_u32(header->plain_region_size,LE)*media_unit);
+ ctx->exefs_offset = (u64)(u8_to_u32(header->exefs_offset,LE)*media_unit);
+ ctx->exefs_size = (u64)(u8_to_u32(header->exefs_size,LE)*media_unit);
+ ctx->exefs_hash_src_size = (u64)(u8_to_u32(header->exefs_hash_size,LE)*media_unit);
+ }
+ ctx->romfs_offset = (u64) (u8_to_u32(header->romfs_offset,LE)*media_unit);
+ ctx->romfs_size = (u64) (u8_to_u32(header->romfs_size,LE)*media_unit);
+ ctx->romfs_hash_src_size = (u64)(u8_to_u32(header->romfs_hash_size,LE)*media_unit);
+ return 0;
+}
+
+void CryptNCCHSection(u8 *buffer, u64 size, u64 src_pos, NCCH_STRUCT *ctx, u8 key[16], u8 type)
+{
+ if(type < 1 || type > 3)
+ return;
+ u8 counter[0x10];
+ ncch_get_counter(ctx,counter,type);
+ ctr_aes_context aes_ctx;
+ memset(&aes_ctx,0x0,sizeof(ctr_aes_context));
+ ctr_init_counter(&aes_ctx, key, counter);
+ if(src_pos > 0){
+ u32 carry = 0;
+ carry = align_value(src_pos,0x10);
+ carry = carry/0x10;
+ ctr_add_counter(&aes_ctx,carry);
+ }
+ ctr_crypt_counter(&aes_ctx, buffer, buffer, size);
+ return;
+}
+
+void ncch_get_counter(NCCH_STRUCT *ctx, u8 counter[16], u8 type)
+{
+ u8 *titleID = ctx->titleID;
+ u32 i;
+ u32 x = 0;
+
+ memset(counter, 0, 16);
+
+ if (ctx->version == 2 || ctx->version == 0)
+ {
+ for(i=0; i<8; i++)
+ counter[i] = titleID[7-i];
+ counter[8] = type;
+ }
+ else if (ctx->version == 1)
+ {
+ switch(type){
+ case ncch_ExHeader : x = ctx->exheader_offset; break;
+ case ncch_exefs : x = ctx->exefs_offset; break;
+ case ncch_romfs : x = ctx->romfs_offset; break;
+ }
+ for(i=0; i<8; i++)
+ counter[i] = titleID[i];
+ for(i=0; i<4; i++)
+ counter[12+i] = x>>((3-i)*8);
+ }
+}
\ No newline at end of file
diff --git a/ncch.h b/ncch.h
new file mode 100644
index 0000000..a58ac6f
--- /dev/null
+++ b/ncch.h
@@ -0,0 +1,238 @@
+#ifndef _NCCH_H_
+#define _NCCH_H_
+
+typedef enum
+{
+ NCCH_MEMERROR = -1,
+ SAVE_DATA_TOO_LARGE = -2,
+ NCCH_SECTION_NOT_EXIST = -3,
+ UNABLE_TO_LOAD_NCCH_KEY = -4,
+ NCCH_EXPORT_BUFFER_TOO_SMALL = -5,
+ NO_ROMFS_IN_CFA = -6,
+ NO_EXHEADER_IN_CXI = -7,
+ NO_EXEFS_IN_CXI = -8,
+ // SigCheck Errors
+ CXI_CORRUPT = -9,
+ ACCESSDESC_SIG_BAD = -10,
+ NCCH_HDR_SIG_BAD = -11,
+ // HashCheck Errors
+ ExHeader_Hashfail = -12,
+ Logo_Hashfail = -13,
+ ExeFs_Hashfail = -14,
+ RomFs_Hashfail = -15,
+ // Others
+ NCCH_BAD_YAML_SET = -16,
+ DATA_POS_DNE = -17,
+} ncch_errors;
+
+typedef enum
+{
+ ncch_ExHeader = 1,
+ ncch_exefs,
+ ncch_romfs,
+ ncch_Logo,
+ ncch_PlainRegion,
+} ncch_section;
+
+typedef enum
+{
+ NoKey,
+ KeyIsNormalFixed,
+ KeyIsSystemFixed,
+ KeyIsUnFixed,
+ KeyIsUnFixed2,
+} ncch_key_type;
+
+typedef enum
+{
+ SecureCrypto2 = 3,
+ ContentPlatform = 4,
+ ContentType = 5,
+ ContentUnitSize = 6,
+ OtherFlag = 7
+} ncch_flags;
+
+typedef enum
+{
+ FixedCryptoKey = 0x1,
+ NoMountRomFs = 0x2,
+ NoCrypto = 0x4,
+} ncch_otherflag_bitmask;
+
+typedef enum
+{
+ RomFS = 0x1,
+ ExeFS = 0x2,
+ SystemUpdate = 0x4,
+ Manual = 0x8,
+ Child = (0x4|0x8),
+ Trial = 0x10
+} ncch_content_bitmask;
+
+typedef struct
+{
+ u16 version;
+ u32 exheader_offset;
+ u32 exheader_size;
+ u64 logo_offset;
+ u64 logo_size;
+ u64 plain_region_offset;
+ u64 plain_region_size;
+ u64 exefs_offset;
+ u64 exefs_size;
+ u64 exefs_hash_src_size;
+ u64 romfs_offset;
+ u64 romfs_size;
+ u64 romfs_hash_src_size;
+ u8 titleID[8];
+ u8 programID[8];
+}NCCH_STRUCT;
+
+typedef struct
+{
+ u8 magic[4];
+ u8 content_size[4];
+ u8 title_id[8];
+ u8 maker_code[2];
+ u8 version[2];
+ u8 reserved_0[4];
+ u8 program_id[8];
+ u8 reserved_1[0x10];
+ u8 logo_sha_256_hash[0x20];
+ u8 product_code[0x10];
+ u8 extended_header_sha_256_hash[0x20];
+ u8 extended_header_size[4];
+ u8 reserved_2[4];
+ u8 flags[8];
+ u8 plain_region_offset[4];
+ u8 plain_region_size[4];
+ u8 logo_region_offset[4];
+ u8 logo_region_size[4];
+ u8 exefs_offset[4];
+ u8 exefs_size[4];
+ u8 exefs_hash_size[4];
+ u8 reserved_4[4];
+ u8 romfs_offset[4];
+ u8 romfs_size[4];
+ u8 romfs_hash_size[4];
+ u8 reserved_5[4];
+ u8 exefs_sha_256_hash[0x20];
+ u8 romfs_sha_256_hash[0x20];
+} NCCH_Header;
+
+
+typedef struct
+{
+ keys_struct *keys;
+ desc_settings *yaml_set;
+ COMPONENT_STRUCT *out;
+
+ struct{
+ u8 *PubK;
+ u8 *PrivK;
+ } CxiRsaKey;
+
+ struct
+ {
+ u32 MediaSize;
+
+ fixed_accessdesc_type accessdesc;
+
+ bool IncludeExeFsLogo;
+ bool CompressCode;
+ bool UseOnSD;
+ bool Encrypt;
+ bool FreeProductCode;
+ bool IsCfa;
+ bool IsBuildingCodeSection;
+ } Options;
+
+ struct
+ {
+ FILE *elf;
+ u64 elf_size;
+
+ FILE *banner;
+ u64 banner_size;
+
+ FILE *icon;
+ u64 icon_size;
+
+ FILE *logo;
+ u64 logo_size;
+
+ FILE *code;
+ u64 code_size;
+
+ FILE *exheader;
+ u64 exheader_size;
+
+ FILE *romfs;
+ u64 romfs_size;
+
+ FILE *plainregion;
+ u64 plainregion_size;
+ } ComponentFilePtrs;
+
+ struct
+ {
+ COMPONENT_STRUCT Code;
+ COMPONENT_STRUCT Banner;
+ COMPONENT_STRUCT Icon;
+ } ExeFs_Sections;
+
+ struct
+ {
+ u32 TextAddress;
+ u32 TextSize;
+ u32 TextMaxPages;
+ u32 ROAddress;
+ u32 ROSize;
+ u32 ROMaxPages;
+ u32 DataAddress;
+ u32 DataSize;
+ u32 DataMaxPages;
+ u32 BSS_Size;
+ } CodeDetails;
+
+ struct
+ {
+ u64 TotalContentSize;
+ COMPONENT_STRUCT CommonHeader;
+ COMPONENT_STRUCT ExHeader;
+ u64 LogoOffset;
+ COMPONENT_STRUCT Logo;
+ u64 PlainRegionOffset;
+ COMPONENT_STRUCT PlainRegion;
+ u64 ExeFsOffset;
+ COMPONENT_STRUCT ExeFs;
+ u64 RomFsOffset;
+ COMPONENT_STRUCT RomFs;
+ } Sections;
+
+} ncch_settings;
+
+#endif
+
+// NCCH Build Functions
+int build_NCCH(user_settings *usrset);
+
+
+// NCCH Read Functions
+int VerifyNCCH(u8 *ncch, keys_struct *keys, bool SuppressOutput);
+
+u8* RetargetNCCH(FILE *fp, u64 size, u8 *TitleId, u8 *ProgramId, keys_struct *keys);
+
+NCCH_Header* GetNCCH_CommonHDR(void *out, FILE *fp, u8 *buf);
+bool IsNCCH(FILE *fp, u8 *buf);
+bool IsCfa(NCCH_Header* hdr);
+u32 GetNCCH_MediaUnitSize(NCCH_Header* hdr);
+u32 GetNCCH_MediaSize(NCCH_Header* hdr);
+ncch_key_type GetNCCHKeyType(NCCH_Header* hdr);
+
+int GetNCCHSection(u8 *dest, u64 dest_max_size, u64 src_pos, u8 *ncch, NCCH_STRUCT *ncch_ctx, keys_struct *keys, ncch_section section);
+u8* GetNCCHKey(NCCH_Header* hdr, keys_struct *keys);
+
+int GetCXIStruct(NCCH_STRUCT *ctx, NCCH_Header *header);
+void ncch_get_counter(NCCH_STRUCT *ctx, u8 counter[16], u8 type);
+void CryptNCCHSection(u8 *buffer, u64 size, u64 src_pos, NCCH_STRUCT *ctx, u8 key[16], u8 type);
\ No newline at end of file
diff --git a/ncsd.c b/ncsd.c
new file mode 100644
index 0000000..c79acba
--- /dev/null
+++ b/ncsd.c
@@ -0,0 +1,554 @@
+#include "lib.h"
+#include "ncch.h"
+#include "exheader.h"
+#include "ncsd.h"
+
+// Private Prototypes
+
+/* RSA Crypto */
+int SignCCI(u8 *Signature, u8 *NCSD_HDR);
+int CheckCCISignature(u8 *Signature, u8 *NCSD_HDR);
+
+/* cci_settings tools */
+void init_CCISettings(cci_settings *set);
+int get_CCISettings(cci_settings *cciset, user_settings *usrset);
+void free_CCISettings(cci_settings *set);
+
+/* CCI Data Gen/Write */
+int GenNCSDHeader(cci_settings *cciset, user_settings *usrset);
+int GenCardInfoHeader(cci_settings *cciset, user_settings *usrset);
+int WriteCCI_HDR_ToFile(cci_settings *cciset);
+int WriteCCI_Content_ToFile(cci_settings *cciset,user_settings *usrset);
+int WriteCCI_DummyBytes(cci_settings *cciset);
+
+/* Get Data from Content Files */
+int CheckContent0(cci_settings *cciset, user_settings *usrset);
+int GetDataFromContent0(cci_settings *cciset, user_settings *usrset);
+int GetContentFP(cci_settings *cciset, user_settings *usrset);
+
+/* Get Data from YAML Settings */
+int GetMediaSize(cci_settings *cciset, user_settings *usrset);
+u64 GetUnusedSize(u64 MediaSize, u8 CardType);
+int GetMediaType(cci_settings *cciset, user_settings *usrset);
+int GetPlatform(cci_settings *cciset, user_settings *usrset);
+int GetCardDevice(cci_settings *cciset, user_settings *usrset);
+int GetWriteableAddress(cci_settings *cciset, user_settings *usrset);
+int GetCardInfoBitmask(cci_settings *cciset, user_settings *usrset);
+
+int CheckMediaSize(cci_settings *cciset);
+
+static InternalCCI_Context ctx;
+
+// Code
+int build_CCI(user_settings *usrset)
+{
+ int result = 0;
+
+ // Init Settings
+ cci_settings *cciset = malloc(sizeof(cci_settings));
+ if(!cciset) {fprintf(stderr,"[CCI ERROR] MEM ERROR\n"); return MEM_ERROR;}
+ init_CCISettings(cciset);
+
+ // Get Settings
+ result = get_CCISettings(cciset,usrset);
+ if(result) goto finish;
+
+ // Create Output File
+ cciset->out = fopen(usrset->outfile,"wb");
+ if(!cciset->out){
+ fprintf(stderr,"[CCI ERROR] Failed to create '%s'\n",usrset->outfile);
+ result = FAILED_TO_CREATE_OUTFILE;
+ goto finish;
+ }
+
+ // Generate NCSD Header and Additional Header
+ result = GenNCSDHeader(cciset,usrset);
+ if(result) goto finish;
+ GenCardInfoHeader(cciset,usrset);
+
+ // Write to File
+ WriteCCI_HDR_ToFile(cciset);
+ result = WriteCCI_Content_ToFile(cciset,usrset);
+ if(result) goto finish;
+
+ // Fill out file if necessary
+ if(cciset->MediaFootPadding) WriteCCI_DummyBytes(cciset);
+
+ // Close output file
+finish:
+ if(result != FAILED_TO_CREATE_OUTFILE && cciset->out) fclose(cciset->out);
+ free_CCISettings(cciset);
+ return result;
+}
+
+
+int SignCCI(u8 *Signature, u8 *NCSD_HDR)
+{
+ return ctr_sig(NCSD_HDR,sizeof(NCSD_Header),Signature,ctx.keys->rsa.CCI_Pub,ctx.keys->rsa.CCI_Priv,RSA_2048_SHA256,CTR_RSA_SIGN);
+}
+
+int CheckCCISignature(u8 *Signature, u8 *NCSD_HDR)
+{
+ return ctr_sig(NCSD_HDR,sizeof(NCSD_Header),Signature,ctx.keys->rsa.CCI_Pub,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY);
+}
+
+void init_CCISettings(cci_settings *set)
+{
+ memset(set,0,sizeof(cci_settings));
+ memset(&ctx,0,sizeof(InternalCCI_Context));
+}
+
+int get_CCISettings(cci_settings *cciset, user_settings *usrset)
+{
+ ctx.keys = &usrset->keys;
+ int result = 0;
+
+ /* Importing Data from Content0 */
+ result = CheckContent0(cciset,usrset);
+ if(result) return result;
+
+ result = GetDataFromContent0(cciset,usrset);
+ if(result) return result;
+
+ result = GetMediaSize(cciset,usrset);
+ if(result) return result;
+
+ /* Getting Data from YAML */
+ result = GetMediaType(cciset,usrset);
+ if(result) return result;
+
+ result = GetPlatform(cciset,usrset);
+ if(result) return result;
+
+ result = GetCardDevice(cciset,usrset);
+ if(result) return result;
+
+ result = GetContentFP(cciset,usrset);
+ if(result) return result;
+
+ result = CheckMediaSize(cciset);
+ if(result) return result;
+
+ /** Card Info Header Data **/
+ result = GetWriteableAddress(cciset,usrset);
+ if(result) return result;
+
+ result = GetCardInfoBitmask(cciset,usrset);
+ if(result) return result;
+
+ /* All Done */
+ return 0;
+}
+
+void free_CCISettings(cci_settings *set)
+{
+ if(set->content){
+ for(int i = 1; i < 8; i++) {
+ if(set->content[i]) fclose(set->content[i]);
+ }
+ free(set->content);
+ }
+ free(set);
+}
+
+int GenNCSDHeader(cci_settings *cciset, user_settings *usrset)
+{
+ memcpy((u8*)ctx.commonHDR.magic,"NCSD",4);
+ u32_to_u8((u8*)ctx.commonHDR.media_size,(cciset->MediaSize/cciset->MediaUnitSize),LE);
+ memcpy((u8*)ctx.commonHDR.title_id,cciset->MediaID,8);
+ for(int i = 0; i < 8; i++){
+ u32_to_u8((u8*)ctx.commonHDR.offsetsize_table[i].offset,(cciset->ContentOffset[i]/cciset->MediaUnitSize),LE);
+ u32_to_u8((u8*)ctx.commonHDR.offsetsize_table[i].size,(cciset->ContentSize[i]/cciset->MediaUnitSize),LE);
+ memcpy((u8*)ctx.commonHDR.partition_id_table[i],cciset->ContentTitleID[i],8);
+ }
+ memcpy((u8*)ctx.commonHDR.partition_flags,cciset->NCSD_Flags,8);
+ if(SignCCI(ctx.Signature,(u8*)&ctx.commonHDR) != Good){
+ fprintf(stderr,"[CCI ERROR] Failed to sign CCI\n");
+ return CCI_SIG_FAIL;
+ }
+ return 0;
+}
+
+int GenCardInfoHeader(cci_settings *cciset, user_settings *usrset)
+{
+ u32_to_u8((u8*)ctx.CardInfoHDR.writable_address,(cciset->WritableAddress/cciset->MediaUnitSize),LE);
+ u32_to_u8((u8*)ctx.CardInfoHDR.card_info_bitmask,cciset->CardInfoBitmask,BE);
+ u32_to_u8((u8*)ctx.CardInfoHDR.media_size_used,cciset->TotalContentSize,LE);
+ memcpy((u8*)ctx.CardInfoHDR.ncch_0_title_id,cciset->ContentTitleID[0],8);
+ memcpy((u8*)ctx.CardInfoHDR.initial_data,cciset->InitialData,0x30);
+ if(!(usrset->OmitImportedNcchHdr && !usrset->IsBuildingNCCH0)) memcpy((u8*)ctx.CardInfoHDR.ncch_0_header,cciset->NCCH_HDR,0x100);
+ memcpy((u8*)ctx.DevCardInfoHDR.TitleKey,cciset->TitleKey,0x10);
+ return 0;
+}
+
+int WriteCCI_HDR_ToFile(cci_settings *cciset)
+{
+ WriteBuffer(ctx.Signature,0x100,0,cciset->out);
+ WriteBuffer((u8*)&ctx.commonHDR,sizeof(NCSD_Header),0x100,cciset->out);
+ WriteBuffer((u8*)&ctx.CardInfoHDR,sizeof(CardInfo_Header),0x200,cciset->out);
+ WriteBuffer((u8*)&ctx.DevCardInfoHDR,sizeof(Dev_CardInfo_Header),0x1200,cciset->out);
+ return 0;
+}
+
+int WriteCCI_Content_ToFile(cci_settings *cciset,user_settings *usrset)
+{
+ // Write Content 0
+ WriteBuffer(cciset->ncch0,cciset->ContentSize[0],cciset->ContentOffset[0],cciset->out);
+ free(usrset->Content0.buffer);
+ usrset->Content0.buffer = NULL;
+ usrset->Content0.size = 0;
+
+ // Add additional contents, recreating them with their new TitleID
+ for(int i = 1; i < 8; i++){
+ if(cciset->content[i]){
+ u8 *ContentBuff = RetargetNCCH(cciset->content[i],cciset->ContentSize[i],cciset->ContentTitleID[i],cciset->MediaID,ctx.keys);
+ if(!ContentBuff){
+ fprintf(stderr,"[CCI ERROR] Could not import content %d to CCI\n",i);
+ return FAILED_TO_IMPORT_FILE;
+ }
+ WriteBuffer(ContentBuff,cciset->ContentSize[i],cciset->ContentOffset[i],cciset->out);
+ free(ContentBuff);
+ }
+ }
+ return 0;
+}
+
+int WriteCCI_DummyBytes(cci_settings *cciset)
+{
+ // Seeking end of CCI Data
+ fseek_64(cciset->out,cciset->TotalContentSize,SEEK_SET);
+
+ // Determining Size of Dummy Bytes
+ u64 len = cciset->MediaSize - cciset->TotalContentSize;
+
+ // Creating Buffer of Dummy Bytes
+ u8 dummy_bytes[cciset->MediaUnitSize];
+ memset(&dummy_bytes,0xff,cciset->MediaUnitSize);
+
+ // Writing Dummy Bytes to file
+ for(u64 i = 0; i < len; i += cciset->MediaUnitSize){
+ fwrite(&dummy_bytes,cciset->MediaUnitSize,1,cciset->out);
+ }
+
+ return 0;
+}
+
+int GetContentFP(cci_settings *cciset, user_settings *usrset)
+{
+ cciset->content = malloc(sizeof(FILE*)*8);
+ if(!cciset->content){
+ fprintf(stderr,"[CCI ERROR] MEM ERROR\n");
+ return MEM_ERROR;
+ }
+ memset(cciset->content,0,sizeof(FILE*)*8);
+
+ for(int i = 1; i < 8; i++){
+ if(usrset->ContentPath[i]){
+ cciset->content[i] = fopen(usrset->ContentPath[i],"rb");
+ if(!cciset->content[i]){ // Checking if file could be opened
+ fprintf(stderr,"[CCI ERROR] Failed to create '%s'\n",usrset->outfile);
+ return FAILED_TO_OPEN_FILE;
+ }
+ if(!IsNCCH(cciset->content[i],NULL)){ // Checking if NCCH
+ fprintf(stderr,"[CCI ERROR] Content '%s' is invalid\n",usrset->ContentPath[i]);
+ return NCSD_INVALID_NCCH0;
+ }
+
+ // Getting NCCH Header
+ NCCH_Header *hdr = malloc(sizeof(NCCH_Header));;
+ GetNCCH_CommonHDR(hdr,cciset->content[i],NULL);
+
+ if(GetNCCH_MediaUnitSize(hdr) != cciset->MediaUnitSize){ // Checking if Media Unit Size matches CCI
+ fprintf(stderr,"[CCI ERROR] Content '%s' is invalid\n",usrset->ContentPath[i]);
+ return NCSD_INVALID_NCCH0;
+ }
+
+ memcpy(&cciset->ContentTitleID[i],cciset->MediaID,8); // Set TitleID
+
+ // Modify TitleID Accordingly
+ u16 tmp = u8_to_u16(&hdr->title_id[6],LE);
+ tmp |= (i+4);
+ u16_to_u8(&cciset->ContentTitleID[i][6],tmp,LE);
+
+ cciset->ContentSize[i] = GetNCCH_MediaSize(hdr)*cciset->MediaUnitSize;
+ cciset->ContentOffset[i] = cciset->TotalContentSize;
+
+ cciset->TotalContentSize += cciset->ContentSize[i];
+
+ free(hdr);
+ }
+ }
+ return 0;
+}
+
+int CheckContent0(cci_settings *cciset, user_settings *usrset)
+{
+ if(!usrset->Content0.size)
+ return NCSD_NO_NCCH0;
+ cciset->ncch0 = usrset->Content0.buffer;
+ cciset->ncch0_FileLen = usrset->Content0.size;
+
+ if(!IsNCCH(NULL,cciset->ncch0))
+ return NCSD_INVALID_NCCH0;
+
+ return 0;
+}
+
+int GetDataFromContent0(cci_settings *cciset, user_settings *usrset)
+{
+ cciset->TotalContentSize = 0x4000;
+
+ NCCH_Header *hdr;
+
+ hdr = GetNCCH_CommonHDR(NULL,NULL,cciset->ncch0);
+
+ cciset->NCCH_HDR = hdr;
+
+ //memdump(stdout,"ncch0 head: ",(cciset->ncch0+0x100),0x100);
+ //memdump(stdout,"ncch0 head: ",(u8*)(hdr),0x100);
+
+ memcpy(cciset->MediaID,hdr->title_id,8);
+ memcpy(&cciset->ContentTitleID[0],hdr->title_id,8);
+ if(usrset->GenSDKCardInfoHeader){
+ memcpy(cciset->InitialData,Stock_InitialData,0x30);
+ memcpy(cciset->TitleKey,Stock_TitleKey,0x10);
+ }
+ else{
+ u8 Hash[0x40];
+ ctr_sha(cciset->ncch0,0x80,Hash,CTR_SHA_256);
+ ctr_sha((cciset->ncch0+0x80),0x80,(Hash+0x20),CTR_SHA_256);
+ memcpy(cciset->InitialData,Hash,0x2C);
+ //memcpy(cciset->TitleKey,(Hash+0x30),0x10); // Might Remove
+ }
+
+
+ cciset->NCSD_Flags[MediaUnitSize] = hdr->flags[ContentUnitSize];
+ cciset->MediaUnitSize = GetNCCH_MediaUnitSize(hdr);
+
+ cciset->ContentSize[0] = (u64)(GetNCCH_MediaSize(hdr) * cciset->MediaUnitSize);
+ cciset->ContentOffset[0] = cciset->TotalContentSize;
+
+ cciset->TotalContentSize += cciset->ContentSize[0];
+ return 0;
+}
+
+int GetMediaSize(cci_settings *cciset, user_settings *usrset)
+{
+ char *MediaSizeStr = usrset->yaml_set.DefaultSpec.BasicInfo.MediaSize;
+ if(!MediaSizeStr) cciset->MediaSize = (u64)GB*2;
+ else{
+ if(strcasecmp(MediaSizeStr,"128MB") == 0) cciset->MediaSize = (u64)MB*128;
+ else if(strcasecmp(MediaSizeStr,"256MB") == 0) cciset->MediaSize = (u64)MB*256;
+ else if(strcasecmp(MediaSizeStr,"512MB") == 0) cciset->MediaSize = (u64)MB*512;
+ else if(strcasecmp(MediaSizeStr,"1GB") == 0) cciset->MediaSize = (u64)GB*1;
+ else if(strcasecmp(MediaSizeStr,"2GB") == 0) cciset->MediaSize = (u64)GB*2;
+ else if(strcasecmp(MediaSizeStr,"4GB") == 0) cciset->MediaSize = (u64)GB*4;
+ else if(strcasecmp(MediaSizeStr,"8GB") == 0) cciset->MediaSize = (u64)GB*8;
+ else if(strcasecmp(MediaSizeStr,"16GB") == 0) cciset->MediaSize = (u64)GB*16;
+ else if(strcasecmp(MediaSizeStr,"32GB") == 0) cciset->MediaSize = (u64)GB*32;
+ else {
+ fprintf(stderr,"[CCI ERROR] Invalid MediaSize: %s\n",MediaSizeStr);
+ return INVALID_YAML_OPT;
+ }
+ }
+
+ if(usrset->yaml_set.DefaultSpec.BasicInfo.MediaFootPadding != -1) cciset->MediaFootPadding = usrset->yaml_set.DefaultSpec.BasicInfo.MediaFootPadding;
+
+ return 0;
+}
+
+u64 GetUnusedSize(u64 MediaSize, u8 CardType)
+{
+ if(CardType == CARD1){
+ switch(MediaSize){
+ case (u64)MB*128: return (u64)2621440;
+ case (u64)MB*256: return (u64)5242880;
+ case (u64)MB*512: return (u64)10485760;
+ case (u64)GB*1: return (u64)73924608;
+ case (u64)GB*2: return (u64)147324928;
+ case (u64)GB*4: return (u64)294649856;
+ case (u64)GB*8: return (u64)587202560;
+ default: return (u64)((MediaSize/MB)*0x11800); // Aprox
+ }
+ }
+ else if(CardType == CARD2){
+ switch(MediaSize){
+ case (u64)MB*512: return (u64)37224448;
+ case (u64)GB*1: return (u64)73924608;
+ case (u64)GB*2: return (u64)147324928;
+ case (u64)GB*4: return (u64)294649856;
+ case (u64)GB*8: return (u64)587202560;
+ default: return (u64)((MediaSize/MB)*0x11800); // Aprox
+ }
+ }
+ return 0;
+}
+
+int GetMediaType(cci_settings *cciset, user_settings *usrset)
+{
+ char *MediaTypeStr = usrset->yaml_set.DefaultSpec.CardInfo.MediaType;
+ if(!MediaTypeStr) cciset->NCSD_Flags[MediaTypeIndex] = CARD1;
+ else{
+ if(strcasecmp(MediaTypeStr,"Card1") == 0) cciset->NCSD_Flags[MediaTypeIndex] = CARD1;
+ else if(strcasecmp(MediaTypeStr,"Card2") == 0) cciset->NCSD_Flags[MediaTypeIndex] = CARD2;
+ else {
+ fprintf(stderr,"[CCI ERROR] Invalid MediaType: %s\n",MediaTypeStr);
+ return INVALID_YAML_OPT;
+ }
+ }
+ return 0;
+}
+
+int GetPlatform(cci_settings *cciset, user_settings *usrset)
+{
+ char *PlatformStr = usrset->yaml_set.DefaultSpec.TitleInfo.Platform;
+ if(!PlatformStr) cciset->NCSD_Flags[MediaPlatformIndex] = CTR;
+ else{
+ if(strcasecmp(PlatformStr,"ctr") == 0) cciset->NCSD_Flags[MediaPlatformIndex] = CTR;
+ else {
+ fprintf(stderr,"[CCI ERROR] Invalid Platform: %s\n",PlatformStr);
+ return INVALID_YAML_OPT;
+ }
+ }
+ return 0;
+}
+
+int GetCardDevice(cci_settings *cciset, user_settings *usrset)
+{
+ char *CardDeviceStr = usrset->yaml_set.DefaultSpec.CardInfo.CardDevice;
+ if(!CardDeviceStr) cciset->NCSD_Flags[CardDeviceFlag] = CARD_DEVICE_NONE;
+ else{
+ if(strcmp(CardDeviceStr,"NorFlash") == 0) {
+ cciset->NCSD_Flags[CardDeviceFlag] = CARD_DEVICE_NOR_FLASH;
+ if(cciset->NCSD_Flags[MediaTypeIndex] == CARD2){
+ fprintf(stderr,"[CCI WARNING] 'CardDevice: NorFlash' is invalid on Card2\n");
+ cciset->NCSD_Flags[CardDeviceFlag] = CARD_DEVICE_NONE;
+ }
+ }
+ else if(strcmp(CardDeviceStr,"None") == 0) cciset->NCSD_Flags[CardDeviceFlag] = CARD_DEVICE_NONE;
+ else if(strcmp(CardDeviceStr,"BT") == 0) cciset->NCSD_Flags[CardDeviceFlag] = CARD_DEVICE_BT;
+ else {
+ fprintf(stderr,"[CCI ERROR] Invalid CardDevice: %s\n",CardDeviceStr);
+ return INVALID_YAML_OPT;
+ }
+ }
+ return 0;
+}
+
+int GetWriteableAddress(cci_settings *cciset, user_settings *usrset)
+{
+ int result = GetSaveDataSize_yaml(&cciset->SaveDataSize,usrset);
+ if(result) return result;
+
+ char *WriteableAddressStr = usrset->yaml_set.DefaultSpec.CardInfo.WritableAddress;;
+
+ cciset->WritableAddress = -1;
+ if(cciset->NCSD_Flags[MediaTypeIndex] != CARD2) return 0; // Can only be set for Card2 Media
+
+ if(WriteableAddressStr){
+ if(strncmp(WriteableAddressStr,"0x",2) != 0){
+ fprintf(stderr,"[CCI ERROR] WritableAddress requires a Hexadecimal value\n");
+ return INVALID_YAML_OPT;
+ }
+ cciset->WritableAddress = strtoul((WriteableAddressStr+2),NULL,16);
+ }
+ if(cciset->WritableAddress == -1){ // If not set manually or is max size
+ if ((cciset->MediaSize / 2) < cciset->SaveDataSize){ // If SaveData size is greater than half the MediaSize
+ u64 saveDataSize = cciset->SaveDataSize / KB;
+ fprintf(stderr,"[CCI ERROR] Too large SaveDataSize %luK\n",saveDataSize);
+ return SAVE_DATA_TOO_LARGE;
+ }
+ if (cciset->SaveDataSize > (u64)(2047*MB)){ // Limit set by Nintendo
+ u64 saveDataSize = cciset->SaveDataSize / KB;
+ fprintf(stderr,"[CCI ERROR] Too large SaveDataSize %luK\n",saveDataSize);
+ return SAVE_DATA_TOO_LARGE;
+ }
+ u64 UnusedSize = GetUnusedSize(cciset->MediaSize,cciset->NCSD_Flags[MediaTypeIndex]); // Need to look into this
+ cciset->WritableAddress = cciset->MediaSize - UnusedSize - cciset->SaveDataSize;
+ }
+ return 0;
+}
+
+int GetCardInfoBitmask(cci_settings *cciset, user_settings *usrset)
+{
+ char *str = usrset->yaml_set.DefaultSpec.CardInfo.CardType;
+ if(!str) cciset->CardInfoBitmask |= 0;
+ else{
+ if(strcasecmp(str,"s1") == 0) cciset->CardInfoBitmask |= 0;
+ else if(strcasecmp(str,"s2") == 0) cciset->CardInfoBitmask |= 0x20;
+ else {
+ fprintf(stderr,"[CCI ERROR] Invalid CardType: %s\n",str);
+ return INVALID_YAML_OPT;
+ }
+ }
+
+ str = usrset->yaml_set.DefaultSpec.CardInfo.CryptoType;
+ if(!str) cciset->CardInfoBitmask |= (3*0x40);
+ else{
+ int Value = strtol(str,NULL,10);
+ if(Value < 0 || Value > 3) {
+ fprintf(stderr,"[CCI ERROR] Invalid CryptoType: %s\n",str);
+ return INVALID_YAML_OPT;
+ }
+ if(Value != 3){
+ fprintf(stderr,"[CCI WARNING] Card crypto type = '%d'\n",Value);
+ }
+ cciset->CardInfoBitmask |= (Value*0x40);
+ }
+
+ return 0;
+}
+
+int CheckMediaSize(cci_settings *cciset)
+{
+ if(cciset->TotalContentSize > cciset->MediaSize){
+ char *MediaSizeStr = NULL;
+ switch(cciset->MediaSize){
+ case (u64)128*MB: MediaSizeStr = " '128MB'"; break;
+ case (u64)256*MB: MediaSizeStr = " '256MB'"; break;
+ case (u64)512*MB: MediaSizeStr = " '512MB'"; break;
+ case (u64)1*GB: MediaSizeStr = " '1GB'"; break;
+ case (u64)2*GB: MediaSizeStr = " '2GB'"; break;
+ case (u64)4*GB: MediaSizeStr = " '4GB'"; break;
+ case (u64)8*GB: MediaSizeStr = " '8GB'"; break;
+ case (u64)16*GB: MediaSizeStr = " '16GB'"; break;
+ case (u64)32*GB: MediaSizeStr = " '32GB'"; break;
+ default: MediaSizeStr = ""; break;
+ }
+ fprintf(stderr,"[CCI ERROR] MediaSize%s is too Small\n",MediaSizeStr);
+ return INVALID_YAML_OPT;
+ }
+ return 0;
+}
+
+bool IsCci(u8 *ncsd)
+{
+ NCSD_Header *hdr = (NCSD_Header*)(ncsd+0x100);
+ if(!hdr) return false;
+ if(memcmp(hdr->magic,"NCSD",4)!=0) return false;
+ if(hdr->partition_flags[MediaPlatformIndex] != CTR) return false;
+ if(hdr->partition_flags[MediaTypeIndex] != CARD1 && hdr->partition_flags[MediaTypeIndex] != CARD2) return false;
+ return true;
+}
+
+u8* GetPartition(u8 *ncsd, u8 index)
+{
+ return (u8*)(ncsd+GetPartitionOffset(ncsd,index));
+}
+
+
+u64 GetPartitionOffset(u8 *ncsd, u8 index)
+{
+ NCSD_Header *hdr = (NCSD_Header*)(ncsd+0x100);
+ u32 media_size = 0x200*pow(2,hdr->partition_flags[MediaUnitSize]);
+ u32 offset = u8_to_u64(hdr->offsetsize_table[index].offset,LE);
+ return offset*media_size;
+}
+
+u64 GetPartitionSize(u8 *ncsd, u8 index)
+{
+ NCSD_Header *hdr = (NCSD_Header*)(ncsd+0x100);
+ u32 media_size = 0x200*pow(2,hdr->partition_flags[MediaUnitSize]);
+ u32 size = u8_to_u64(hdr->offsetsize_table[index].size,LE);
+ return size*media_size;
+}
diff --git a/ncsd.h b/ncsd.h
new file mode 100644
index 0000000..ff0e7b7
--- /dev/null
+++ b/ncsd.h
@@ -0,0 +1,162 @@
+#ifndef _NCSD_H_
+#define _NCSD_H_
+
+
+// Enums
+typedef enum
+{
+ NCSD_NO_NCCH0 = -1,
+ NCSD_INVALID_NCCH0 = -2,
+ INVALID_YAML_OPT = -3,
+ CCI_SIG_FAIL = -4,
+
+} ncsd_errors;
+
+typedef enum
+{
+ FW6x_SaveCryptoFlag = 1,
+ CardDeviceFlag = 3,
+ MediaPlatformIndex = 4,
+ MediaTypeIndex = 5,
+ MediaUnitSize = 6,
+ OldCardDeviceFlag = 7
+} FlagIndex;
+
+typedef enum
+{
+ CARD_DEVICE_NOR_FLASH = 1,
+ CARD_DEVICE_NONE = 2,
+ CARD_DEVICE_BT = 3
+} _CardDevice;
+
+typedef enum
+{
+ CTR = 1,
+} _PlatformIndex;
+
+typedef enum
+{
+ INNER_DEVICE,
+ CARD1,
+ CARD2,
+ EXTENDED_DEVICE
+} _TypeIndex;
+
+// Structs
+typedef struct
+{
+ u8 offset[4];
+ u8 size[4];
+} partition_offsetsize;
+
+typedef struct
+{
+ u8 magic[4];
+ u8 media_size[4];
+ u8 title_id[8];
+ u8 partitions_fs_type[8];
+ u8 partitions_crypto_type[8];
+ partition_offsetsize offsetsize_table[8];
+ u8 exheader_hash[0x20];
+ u8 additional_header_size[0x4];
+ u8 sector_zero_offset[0x4];
+ u8 partition_flags[8];
+ u8 partition_id_table[8][8];
+ u8 reserved[0x30];
+} NCSD_Header;
+
+typedef struct
+{
+ u8 writable_address[4];
+ u8 card_info_bitmask[4];
+ // Notes
+ u8 reserved_0[0xf8];
+ u8 media_size_used[8];
+ u8 reserved_1[0x18];
+ u8 cver_title_id[8];
+ u8 cver_title_version[2];
+ u8 reserved_2[0xcd6];
+ //
+ u8 ncch_0_title_id[8];
+ u8 reserved_3[8];
+ u8 initial_data[0x30];
+ u8 reserved_4[0xc0];
+ u8 ncch_0_header[0x100];
+} CardInfo_Header;
+
+typedef struct
+{
+ u8 CardDeviceReserved1[0x200];
+ u8 TitleKey[0x10];
+ u8 CardDeviceReserved2[0xf0];
+} Dev_CardInfo_Header;
+
+typedef struct
+{
+ u8 Signature[0x100];
+ NCSD_Header commonHDR;
+ CardInfo_Header CardInfoHDR;
+ Dev_CardInfo_Header DevCardInfoHDR;
+ u8 *ContentImportBuffer;
+ keys_struct *keys;
+} InternalCCI_Context;
+
+typedef struct
+{
+ u64 MediaSize;
+ u8 MediaID[8];
+ u8 NCSD_Flags[8];
+ u64 SaveDataSize;
+ u64 WritableAddress;
+ u32 CardInfoBitmask;
+
+ u8 InitialData[0x30];
+ NCCH_Header *NCCH_HDR;
+ u8 TitleKey[0x10];
+
+ u8 *ncch0;
+ u64 ncch0_FileLen;
+ FILE **content;
+ u64 ContentSize[CCI_MAX_CONTENT];
+ u64 ContentOffset[CCI_MAX_CONTENT];
+ u8 ContentTitleID[CCI_MAX_CONTENT][8];
+ u64 TotalContentSize;
+
+ bool MediaFootPadding;
+ u32 MediaUnitSize;
+
+ FILE *out;
+} cci_settings;
+
+static const u8 Stock_InitialData[0x30] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xAD, 0x88,
+ 0xAC, 0x41, 0xA2, 0xB1, 0x5E, 0x8F,
+ 0x66, 0x9C, 0x97, 0xE5, 0xE1, 0x5E,
+ 0xA3, 0xEB, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 Stock_TitleKey[0x10] =
+{
+ 0x6E, 0xC7, 0x5F, 0xB2, 0xE2, 0xB4,
+ 0x87, 0x46, 0x1E, 0xDD, 0xCB, 0xB8,
+ 0x97, 0x11, 0x92, 0xBA
+};
+
+#endif
+
+// Public Prototypes
+
+
+// Build Functions
+int build_CCI(user_settings *usrset);
+
+// Read Functions
+bool IsCci(u8 *ncsd);
+u8* GetPartition(u8 *ncsd, u8 index);
+u64 GetPartitionOffset(u8 *ncsd, u8 index);
+u64 GetPartitionSize(u8 *ncsd, u8 index);
\ No newline at end of file
diff --git a/polarssl/aes.c b/polarssl/aes.c
new file mode 100644
index 0000000..6456c54
--- /dev/null
+++ b/polarssl/aes.c
@@ -0,0 +1,1352 @@
+/*
+ * FIPS-197 compliant AES implementation
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
+ *
+ * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
+ * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_AES_C)
+
+#include "polarssl/aes.h"
+#if defined(POLARSSL_PADLOCK_C)
+#include "polarssl/padlock.h"
+#endif
+
+#if !defined(POLARSSL_AES_ALT)
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] ) \
+ | ( (uint32_t) (b)[(i) + 1] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 3] << 24 ); \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
+}
+#endif
+
+#if defined(POLARSSL_PADLOCK_C) && \
+ ( defined(POLARSSL_HAVE_X86) || defined(PADLOCK_ALIGN16) )
+static int aes_padlock_ace = -1;
+#endif
+
+#if defined(POLARSSL_AES_ROM_TABLES)
+/*
+ * Forward S-box
+ */
+static const unsigned char FSb[256] =
+{
+ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
+ 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
+ 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
+ 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
+ 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
+ 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
+ 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
+ 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
+ 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
+ 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
+ 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
+ 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
+ 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
+ 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
+ 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
+ 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
+ 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
+ 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
+ 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
+ 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
+ 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
+ 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
+ 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
+ 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
+ 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
+ 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
+ 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
+};
+
+/*
+ * Forward tables
+ */
+#define FT \
+\
+ V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
+ V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
+ V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
+ V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
+ V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
+ V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
+ V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
+ V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
+ V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
+ V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
+ V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
+ V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
+ V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
+ V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
+ V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
+ V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
+ V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
+ V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
+ V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
+ V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
+ V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
+ V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
+ V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
+ V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
+ V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
+ V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
+ V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
+ V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
+ V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
+ V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
+ V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
+ V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
+ V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
+ V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
+ V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
+ V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
+ V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
+ V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
+ V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
+ V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
+ V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
+ V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
+ V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
+ V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
+ V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
+ V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
+ V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
+ V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
+ V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
+ V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
+ V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
+ V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
+ V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
+ V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
+ V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
+ V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
+ V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
+ V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
+ V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
+ V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
+ V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
+ V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
+ V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
+ V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const uint32_t FT0[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const uint32_t FT1[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const uint32_t FT2[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const uint32_t FT3[256] = { FT };
+#undef V
+
+#undef FT
+
+/*
+ * Reverse S-box
+ */
+static const unsigned char RSb[256] =
+{
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
+ 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
+ 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
+ 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
+ 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
+ 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
+ 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
+ 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
+ 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
+ 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
+ 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
+ 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
+ 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
+ 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
+ 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
+ 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
+ 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
+ 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
+ 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
+ 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
+ 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
+ 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
+ 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
+ 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
+ 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
+ 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
+};
+
+/*
+ * Reverse tables
+ */
+#define RT \
+\
+ V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \
+ V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \
+ V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \
+ V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \
+ V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \
+ V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \
+ V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \
+ V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \
+ V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \
+ V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \
+ V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \
+ V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \
+ V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \
+ V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \
+ V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \
+ V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \
+ V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \
+ V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \
+ V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \
+ V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \
+ V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \
+ V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \
+ V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \
+ V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \
+ V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \
+ V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \
+ V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \
+ V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \
+ V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \
+ V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \
+ V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \
+ V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \
+ V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \
+ V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \
+ V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \
+ V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \
+ V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \
+ V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \
+ V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \
+ V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \
+ V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \
+ V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \
+ V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \
+ V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \
+ V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \
+ V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \
+ V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \
+ V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \
+ V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \
+ V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \
+ V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \
+ V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \
+ V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \
+ V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \
+ V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \
+ V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \
+ V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \
+ V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \
+ V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \
+ V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \
+ V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \
+ V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \
+ V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \
+ V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const uint32_t RT0[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const uint32_t RT1[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const uint32_t RT2[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const uint32_t RT3[256] = { RT };
+#undef V
+
+#undef RT
+
+/*
+ * Round constants
+ */
+static const uint32_t RCON[10] =
+{
+ 0x00000001, 0x00000002, 0x00000004, 0x00000008,
+ 0x00000010, 0x00000020, 0x00000040, 0x00000080,
+ 0x0000001B, 0x00000036
+};
+
+#else
+
+/*
+ * Forward S-box & tables
+ */
+static unsigned char FSb[256];
+static uint32_t FT0[256];
+static uint32_t FT1[256];
+static uint32_t FT2[256];
+static uint32_t FT3[256];
+
+/*
+ * Reverse S-box & tables
+ */
+static unsigned char RSb[256];
+static uint32_t RT0[256];
+static uint32_t RT1[256];
+static uint32_t RT2[256];
+static uint32_t RT3[256];
+
+/*
+ * Round constants
+ */
+static uint32_t RCON[10];
+
+/*
+ * Tables generation code
+ */
+#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
+#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
+#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
+
+static int aes_init_done = 0;
+
+static void aes_gen_tables( void )
+{
+ int i, x, y, z;
+ int pow[256];
+ int log[256];
+
+ /*
+ * compute pow and log tables over GF(2^8)
+ */
+ for( i = 0, x = 1; i < 256; i++ )
+ {
+ pow[i] = x;
+ log[x] = i;
+ x = ( x ^ XTIME( x ) ) & 0xFF;
+ }
+
+ /*
+ * calculate the round constants
+ */
+ for( i = 0, x = 1; i < 10; i++ )
+ {
+ RCON[i] = (uint32_t) x;
+ x = XTIME( x ) & 0xFF;
+ }
+
+ /*
+ * generate the forward and reverse S-boxes
+ */
+ FSb[0x00] = 0x63;
+ RSb[0x63] = 0x00;
+
+ for( i = 1; i < 256; i++ )
+ {
+ x = pow[255 - log[i]];
+
+ y = x; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+ x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+ x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+ x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+ x ^= y ^ 0x63;
+
+ FSb[i] = (unsigned char) x;
+ RSb[x] = (unsigned char) i;
+ }
+
+ /*
+ * generate the forward and reverse tables
+ */
+ for( i = 0; i < 256; i++ )
+ {
+ x = FSb[i];
+ y = XTIME( x ) & 0xFF;
+ z = ( y ^ x ) & 0xFF;
+
+ FT0[i] = ( (uint32_t) y ) ^
+ ( (uint32_t) x << 8 ) ^
+ ( (uint32_t) x << 16 ) ^
+ ( (uint32_t) z << 24 );
+
+ FT1[i] = ROTL8( FT0[i] );
+ FT2[i] = ROTL8( FT1[i] );
+ FT3[i] = ROTL8( FT2[i] );
+
+ x = RSb[i];
+
+ RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^
+ ( (uint32_t) MUL( 0x09, x ) << 8 ) ^
+ ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^
+ ( (uint32_t) MUL( 0x0B, x ) << 24 );
+
+ RT1[i] = ROTL8( RT0[i] );
+ RT2[i] = ROTL8( RT1[i] );
+ RT3[i] = ROTL8( RT2[i] );
+ }
+}
+
+#endif
+
+/*
+ * AES key schedule (encryption)
+ */
+int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+ unsigned int i;
+ uint32_t *RK;
+
+#if !defined(POLARSSL_AES_ROM_TABLES)
+ if( aes_init_done == 0 )
+ {
+ aes_gen_tables();
+ aes_init_done = 1;
+
+ }
+#endif
+
+ switch( keysize )
+ {
+ case 128: ctx->nr = 10; break;
+ case 192: ctx->nr = 12; break;
+ case 256: ctx->nr = 14; break;
+ default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
+ }
+
+#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16)
+ if( aes_padlock_ace == -1 )
+ aes_padlock_ace = padlock_supports( PADLOCK_ACE );
+
+ if( aes_padlock_ace )
+ ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );
+ else
+#endif
+ ctx->rk = RK = ctx->buf;
+
+ for( i = 0; i < (keysize >> 5); i++ )
+ {
+ GET_UINT32_LE( RK[i], key, i << 2 );
+ }
+
+ switch( ctx->nr )
+ {
+ case 10:
+
+ for( i = 0; i < 10; i++, RK += 4 )
+ {
+ RK[4] = RK[0] ^ RCON[i] ^
+ ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 );
+
+ RK[5] = RK[1] ^ RK[4];
+ RK[6] = RK[2] ^ RK[5];
+ RK[7] = RK[3] ^ RK[6];
+ }
+ break;
+
+ case 12:
+
+ for( i = 0; i < 8; i++, RK += 6 )
+ {
+ RK[6] = RK[0] ^ RCON[i] ^
+ ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 );
+
+ RK[7] = RK[1] ^ RK[6];
+ RK[8] = RK[2] ^ RK[7];
+ RK[9] = RK[3] ^ RK[8];
+ RK[10] = RK[4] ^ RK[9];
+ RK[11] = RK[5] ^ RK[10];
+ }
+ break;
+
+ case 14:
+
+ for( i = 0; i < 7; i++, RK += 8 )
+ {
+ RK[8] = RK[0] ^ RCON[i] ^
+ ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 );
+
+ RK[9] = RK[1] ^ RK[8];
+ RK[10] = RK[2] ^ RK[9];
+ RK[11] = RK[3] ^ RK[10];
+
+ RK[12] = RK[4] ^
+ ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
+
+ RK[13] = RK[5] ^ RK[12];
+ RK[14] = RK[6] ^ RK[13];
+ RK[15] = RK[7] ^ RK[14];
+ }
+ break;
+
+ default:
+
+ break;
+ }
+
+ return( 0 );
+}
+
+/*
+ * AES key schedule (decryption)
+ */
+int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+ int i, j;
+ aes_context cty;
+ uint32_t *RK;
+ uint32_t *SK;
+ int ret;
+
+ switch( keysize )
+ {
+ case 128: ctx->nr = 10; break;
+ case 192: ctx->nr = 12; break;
+ case 256: ctx->nr = 14; break;
+ default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
+ }
+
+#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16)
+ if( aes_padlock_ace == -1 )
+ aes_padlock_ace = padlock_supports( PADLOCK_ACE );
+
+ if( aes_padlock_ace )
+ ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );
+ else
+#endif
+ ctx->rk = RK = ctx->buf;
+
+ ret = aes_setkey_enc( &cty, key, keysize );
+ if( ret != 0 )
+ return( ret );
+
+ SK = cty.rk + cty.nr * 4;
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+ for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
+ {
+ for( j = 0; j < 4; j++, SK++ )
+ {
+ *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^
+ RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^
+ RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
+ RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
+ }
+ }
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+ memset( &cty, 0, sizeof( aes_context ) );
+
+ return( 0 );
+}
+
+#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ \
+ X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \
+ FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
+ FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
+ FT3[ ( Y3 >> 24 ) & 0xFF ]; \
+ \
+ X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \
+ FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
+ FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
+ FT3[ ( Y0 >> 24 ) & 0xFF ]; \
+ \
+ X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \
+ FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
+ FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
+ FT3[ ( Y1 >> 24 ) & 0xFF ]; \
+ \
+ X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \
+ FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
+ FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
+ FT3[ ( Y2 >> 24 ) & 0xFF ]; \
+}
+
+#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ \
+ X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \
+ RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
+ RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
+ RT3[ ( Y1 >> 24 ) & 0xFF ]; \
+ \
+ X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \
+ RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
+ RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
+ RT3[ ( Y2 >> 24 ) & 0xFF ]; \
+ \
+ X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \
+ RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
+ RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
+ RT3[ ( Y3 >> 24 ) & 0xFF ]; \
+ \
+ X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \
+ RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
+ RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
+ RT3[ ( Y0 >> 24 ) & 0xFF ]; \
+}
+
+/*
+ * AES-ECB block encryption/decryption
+ */
+int aes_crypt_ecb( aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ int i;
+ uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)
+ if( aes_padlock_ace )
+ {
+ if( padlock_xcryptecb( ctx, mode, input, output ) == 0 )
+ return( 0 );
+
+ // If padlock data misaligned, we just fall back to
+ // unaccelerated mode
+ //
+ }
+#endif
+
+ RK = ctx->rk;
+
+ GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++;
+ GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++;
+ GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++;
+ GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
+
+ if( mode == AES_DECRYPT )
+ {
+ for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
+ {
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+ AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+ }
+
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+ X0 = *RK++ ^ \
+ ( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^
+ ( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+ X1 = *RK++ ^ \
+ ( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^
+ ( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+
+ X2 = *RK++ ^ \
+ ( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^
+ ( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+ X3 = *RK++ ^ \
+ ( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^
+ ( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+ }
+ else /* AES_ENCRYPT */
+ {
+ for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
+ {
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+ AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+ }
+
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+ X0 = *RK++ ^ \
+ ( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+ X1 = *RK++ ^ \
+ ( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+
+ X2 = *RK++ ^ \
+ ( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+ X3 = *RK++ ^ \
+ ( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+ }
+
+ PUT_UINT32_LE( X0, output, 0 );
+ PUT_UINT32_LE( X1, output, 4 );
+ PUT_UINT32_LE( X2, output, 8 );
+ PUT_UINT32_LE( X3, output, 12 );
+
+ return( 0 );
+}
+
+/*
+ * AES-CBC buffer encryption/decryption
+ */
+int aes_crypt_cbc( aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[16];
+
+ if( length % 16 )
+ return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH );
+
+#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)
+ if( aes_padlock_ace )
+ {
+ if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 )
+ return( 0 );
+
+ // If padlock data misaligned, we just fall back to
+ // unaccelerated mode
+ //
+ }
+#endif
+
+ if( mode == AES_DECRYPT )
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 16 );
+ aes_crypt_ecb( ctx, mode, input, output );
+
+ for( i = 0; i < 16; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 16 );
+
+ input += 16;
+ output += 16;
+ length -= 16;
+ }
+ }
+ else
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 16; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ aes_crypt_ecb( ctx, mode, output, output );
+ memcpy( iv, output, 16 );
+
+ input += 16;
+ output += 16;
+ length -= 16;
+ }
+ }
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 buffer encryption/decryption
+ */
+int aes_crypt_cfb128( aes_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c;
+ size_t n = *iv_off;
+
+ if( mode == AES_DECRYPT )
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
+
+ c = *input++;
+ *output++ = (unsigned char)( c ^ iv[n] );
+ iv[n] = (unsigned char) c;
+
+ n = (n + 1) & 0x0F;
+ }
+ }
+ else
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
+
+ iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+ n = (n + 1) & 0x0F;
+ }
+ }
+
+ *iv_off = n;
+
+ return( 0 );
+}
+#endif /*POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * AES-CTR buffer encryption/decryption
+ */
+int aes_crypt_ctr( aes_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c, i;
+ size_t n = *nc_off;
+
+ while( length-- )
+ {
+ if( n == 0 ) {
+ aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block );
+
+ for( i = 16; i > 0; i-- )
+ if( ++nonce_counter[i - 1] != 0 )
+ break;
+ }
+ c = *input++;
+ *output++ = (unsigned char)( c ^ stream_block[n] );
+
+ n = (n + 1) & 0x0F;
+ }
+
+ *nc_off = n;
+
+ return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+#endif /* !POLARSSL_AES_ALT */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include
+
+/*
+ * AES test vectors from:
+ *
+ * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip
+ */
+static const unsigned char aes_test_ecb_dec[3][16] =
+{
+ { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58,
+ 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 },
+ { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2,
+ 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 },
+ { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D,
+ 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE }
+};
+
+static const unsigned char aes_test_ecb_enc[3][16] =
+{
+ { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73,
+ 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F },
+ { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11,
+ 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 },
+ { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D,
+ 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 }
+};
+
+static const unsigned char aes_test_cbc_dec[3][16] =
+{
+ { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73,
+ 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 },
+ { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75,
+ 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B },
+ { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75,
+ 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 }
+};
+
+static const unsigned char aes_test_cbc_enc[3][16] =
+{
+ { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84,
+ 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D },
+ { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB,
+ 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 },
+ { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5,
+ 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 }
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 test vectors from:
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ */
+static const unsigned char aes_test_cfb128_key[3][32] =
+{
+ { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
+ { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+ 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+ 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
+ { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+ 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+ 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+ 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char aes_test_cfb128_iv[16] =
+{
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+static const unsigned char aes_test_cfb128_pt[64] =
+{
+ 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+ 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+ 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+ 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+ 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+ 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+ 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+ 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const unsigned char aes_test_cfb128_ct[3][64] =
+{
+ { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
+ 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
+ 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F,
+ 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B,
+ 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40,
+ 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF,
+ 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E,
+ 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 },
+ { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
+ 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
+ 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21,
+ 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A,
+ 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1,
+ 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9,
+ 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0,
+ 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF },
+ { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
+ 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
+ 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8,
+ 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B,
+ 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92,
+ 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9,
+ 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8,
+ 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 }
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * AES-CTR test vectors from:
+ *
+ * http://www.faqs.org/rfcs/rfc3686.html
+ */
+
+static const unsigned char aes_test_ctr_key[3][16] =
+{
+ { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+ 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
+ { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
+ 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
+ { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+ 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
+};
+
+static const unsigned char aes_test_ctr_nonce_counter[3][16] =
+{
+ { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
+ 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
+ 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
+};
+
+static const unsigned char aes_test_ctr_pt[3][48] =
+{
+ { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+ 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23 }
+};
+
+static const unsigned char aes_test_ctr_ct[3][48] =
+{
+ { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79,
+ 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 },
+ { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9,
+ 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88,
+ 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8,
+ 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 },
+ { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9,
+ 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7,
+ 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36,
+ 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53,
+ 0x25, 0xB2, 0x07, 0x2F }
+};
+
+static const int aes_test_ctr_len[3] =
+ { 16, 32, 36 };
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+/*
+ * Checkup routine
+ */
+int aes_self_test( int verbose )
+{
+ int i, j, u, v;
+ unsigned char key[32];
+ unsigned char buf[64];
+ unsigned char prv[16];
+ unsigned char iv[16];
+#if defined(POLARSSL_CIPHER_MODE_CTR) || defined(POLARSSL_CIPHER_MODE_CFB)
+ size_t offset;
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ int len;
+ unsigned char nonce_counter[16];
+ unsigned char stream_block[16];
+#endif
+ aes_context ctx;
+
+ memset( key, 0, 32 );
+
+ /*
+ * ECB mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " AES-ECB-%3d (%s): ", 128 + u * 64,
+ ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+ memset( buf, 0, 16 );
+
+ if( v == AES_DECRYPT )
+ {
+ aes_setkey_dec( &ctx, key, 128 + u * 64 );
+
+ for( j = 0; j < 10000; j++ )
+ aes_crypt_ecb( &ctx, v, buf, buf );
+
+ if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+ for( j = 0; j < 10000; j++ )
+ aes_crypt_ecb( &ctx, v, buf, buf );
+
+ if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ /*
+ * CBC mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " AES-CBC-%3d (%s): ", 128 + u * 64,
+ ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+ memset( iv , 0, 16 );
+ memset( prv, 0, 16 );
+ memset( buf, 0, 16 );
+
+ if( v == AES_DECRYPT )
+ {
+ aes_setkey_dec( &ctx, key, 128 + u * 64 );
+
+ for( j = 0; j < 10000; j++ )
+ aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
+
+ if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+ for( j = 0; j < 10000; j++ )
+ {
+ unsigned char tmp[16];
+
+ aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
+
+ memcpy( tmp, prv, 16 );
+ memcpy( prv, buf, 16 );
+ memcpy( buf, tmp, 16 );
+ }
+
+ if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ /*
+ * CFB128 mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " AES-CFB128-%3d (%s): ", 128 + u * 64,
+ ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( iv, aes_test_cfb128_iv, 16 );
+ memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 );
+
+ offset = 0;
+ aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+ if( v == AES_DECRYPT )
+ {
+ memcpy( buf, aes_test_cfb128_ct[u], 64 );
+ aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
+
+ if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ memcpy( buf, aes_test_cfb128_pt, 64 );
+ aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
+
+ if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ /*
+ * CTR mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " AES-CTR-128 (%s): ",
+ ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );
+ memcpy( key, aes_test_ctr_key[u], 16 );
+
+ offset = 0;
+ aes_setkey_enc( &ctx, key, 128 );
+
+ if( v == AES_DECRYPT )
+ {
+ len = aes_test_ctr_len[u];
+ memcpy( buf, aes_test_ctr_ct[u], len );
+
+ aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+
+ if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ len = aes_test_ctr_len[u];
+ memcpy( buf, aes_test_ctr_pt[u], len );
+
+ aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+
+ if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/aes.h b/polarssl/aes.h
new file mode 100644
index 0000000..0a4519c
--- /dev/null
+++ b/polarssl/aes.h
@@ -0,0 +1,202 @@
+/**
+ * \file aes.h
+ *
+ * \brief AES block cipher
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_AES_H
+#define POLARSSL_AES_H
+
+#include "polarssl/config.h"
+
+#include
+
+#ifdef _MSC_VER
+#include
+typedef UINT32 uint32_t;
+#else
+#include
+#endif
+
+#define AES_ENCRYPT 1
+#define AES_DECRYPT 0
+
+#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
+#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
+
+#if !defined(POLARSSL_AES_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief AES context structure
+ */
+typedef struct
+{
+ int nr; /*!< number of rounds */
+ uint32_t *rk; /*!< AES round keys */
+ uint32_t buf[68]; /*!< unaligned data */
+}
+aes_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief AES key schedule (encryption)
+ *
+ * \param ctx AES context to be initialized
+ * \param key encryption key
+ * \param keysize must be 128, 192 or 256
+ *
+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ */
+int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief AES key schedule (decryption)
+ *
+ * \param ctx AES context to be initialized
+ * \param key decryption key
+ * \param keysize must be 128, 192 or 256
+ *
+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ */
+int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief AES-ECB block encryption/decryption
+ *
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param input 16-byte input block
+ * \param output 16-byte output block
+ *
+ * \return 0 if successful
+ */
+int aes_crypt_ecb( aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+/**
+ * \brief AES-CBC buffer encryption/decryption
+ * Length should be a multiple of the block
+ * size (16 bytes)
+ *
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH
+ */
+int aes_crypt_cbc( aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief AES-CFB128 buffer encryption/decryption.
+ *
+ * Note: Due to the nature of CFB you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
+ *
+ * both
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param length length of the input data
+ * \param iv_off offset in IV (updated after use)
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful
+ */
+int aes_crypt_cfb128( aes_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief AES-CTR buffer encryption/decryption
+ *
+ * Warning: You have to keep the maximum use of your counter in mind!
+ *
+ * Note: Due to the nature of CTR you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
+ *
+ * \param length The length of the data
+ * \param nc_off The offset in the current stream_block (for resuming
+ * within current cipher stream). The offset pointer to
+ * should be 0 at the start of a stream.
+ * \param nonce_counter The 128-bit nonce and counter.
+ * \param stream_block The saved stream-block for resuming. Is overwritten
+ * by the function.
+ * \param input The input data stream
+ * \param output The output data stream
+ *
+ * \return 0 if successful
+ */
+int aes_crypt_ctr( aes_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* POLARSSL_AES_ALT */
+#include "polarssl/aes_alt.h"
+#endif /* POLARSSL_AES_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int aes_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* aes.h */
diff --git a/polarssl/arc4.c b/polarssl/arc4.c
new file mode 100644
index 0000000..85b78f5
--- /dev/null
+++ b/polarssl/arc4.c
@@ -0,0 +1,173 @@
+/*
+ * An implementation of the ARCFOUR algorithm
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The ARCFOUR algorithm was publicly disclosed on 94/09.
+ *
+ * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_ARC4_C)
+
+#include "polarssl/arc4.h"
+
+#if !defined(POLARSSL_ARC4_ALT)
+
+/*
+ * ARC4 key schedule
+ */
+void arc4_setup( arc4_context *ctx, const unsigned char *key, unsigned int keylen )
+{
+ int i, j, a;
+ unsigned int k;
+ unsigned char *m;
+
+ ctx->x = 0;
+ ctx->y = 0;
+ m = ctx->m;
+
+ for( i = 0; i < 256; i++ )
+ m[i] = (unsigned char) i;
+
+ j = k = 0;
+
+ for( i = 0; i < 256; i++, k++ )
+ {
+ if( k >= keylen ) k = 0;
+
+ a = m[i];
+ j = ( j + a + key[k] ) & 0xFF;
+ m[i] = m[j];
+ m[j] = (unsigned char) a;
+ }
+}
+
+/*
+ * ARC4 cipher function
+ */
+int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input,
+ unsigned char *output )
+{
+ int x, y, a, b;
+ size_t i;
+ unsigned char *m;
+
+ x = ctx->x;
+ y = ctx->y;
+ m = ctx->m;
+
+ for( i = 0; i < length; i++ )
+ {
+ x = ( x + 1 ) & 0xFF; a = m[x];
+ y = ( y + a ) & 0xFF; b = m[y];
+
+ m[x] = (unsigned char) b;
+ m[y] = (unsigned char) a;
+
+ output[i] = (unsigned char)
+ ( input[i] ^ m[(unsigned char)( a + b )] );
+ }
+
+ ctx->x = x;
+ ctx->y = y;
+
+ return( 0 );
+}
+
+#endif /* !POLARSSL_ARC4_ALT */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include
+#include
+
+/*
+ * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994:
+ *
+ * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0
+ */
+static const unsigned char arc4_test_key[3][8] =
+{
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char arc4_test_pt[3][8] =
+{
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char arc4_test_ct[3][8] =
+{
+ { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 },
+ { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 },
+ { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A }
+};
+
+/*
+ * Checkup routine
+ */
+int arc4_self_test( int verbose )
+{
+ int i;
+ unsigned char ibuf[8];
+ unsigned char obuf[8];
+ arc4_context ctx;
+
+ for( i = 0; i < 3; i++ )
+ {
+ if( verbose != 0 )
+ printf( " ARC4 test #%d: ", i + 1 );
+
+ memcpy( ibuf, arc4_test_pt[i], 8 );
+
+ arc4_setup( &ctx, arc4_test_key[i], 8 );
+ arc4_crypt( &ctx, 8, ibuf, obuf );
+
+ if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/arc4.h b/polarssl/arc4.h
new file mode 100644
index 0000000..d60be3f
--- /dev/null
+++ b/polarssl/arc4.h
@@ -0,0 +1,98 @@
+/**
+ * \file arc4.h
+ *
+ * \brief The ARCFOUR stream cipher
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ARC4_H
+#define POLARSSL_ARC4_H
+
+#include "polarssl/config.h"
+
+#include
+
+#if !defined(POLARSSL_ARC4_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief ARC4 context structure
+ */
+typedef struct
+{
+ int x; /*!< permutation index */
+ int y; /*!< permutation index */
+ unsigned char m[256]; /*!< permutation table */
+}
+arc4_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief ARC4 key schedule
+ *
+ * \param ctx ARC4 context to be initialized
+ * \param key the secret key
+ * \param keylen length of the key
+ */
+void arc4_setup( arc4_context *ctx, const unsigned char *key, unsigned int keylen );
+
+/**
+ * \brief ARC4 cipher function
+ *
+ * \param ctx ARC4 context
+ * \param length length of the input data
+ * \param input buffer holding the input data
+ * \param output buffer for the output data
+ *
+ * \return 0 if successful
+ */
+int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input,
+ unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* POLARSSL_ARC4_ALT */
+#include "polarssl/arc4_alt.h"
+#endif /* POLARSSL_ARC4_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int arc4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* arc4.h */
diff --git a/polarssl/asn1.h b/polarssl/asn1.h
new file mode 100644
index 0000000..e21ae09
--- /dev/null
+++ b/polarssl/asn1.h
@@ -0,0 +1,246 @@
+/**
+ * \file asn1.h
+ *
+ * \brief Generic ASN.1 parsing
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ASN1_H
+#define POLARSSL_ASN1_H
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_BIGNUM_C)
+#include "polarssl/bignum.h"
+#endif
+
+#include
+
+/**
+ * \addtogroup asn1_module
+ * \{
+ */
+
+/**
+ * \name ASN1 Error codes
+ * These error codes are OR'ed to X509 error codes for
+ * higher error granularity.
+ * ASN1 is a standard to specify data structures.
+ * \{
+ */
+#define POLARSSL_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */
+#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */
+#define POLARSSL_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */
+#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */
+#define POLARSSL_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */
+#define POLARSSL_ERR_ASN1_MALLOC_FAILED -0x006A /**< Memory allocation failed */
+#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */
+
+/* \} name */
+
+/**
+ * \name DER constants
+ * These constants comply with DER encoded the ANS1 type tags.
+ * DER encoding uses hexadecimal representation.
+ * An example DER sequence is:\n
+ * - 0x02 -- tag indicating INTEGER
+ * - 0x01 -- length in octets
+ * - 0x05 -- value
+ * Such sequences are typically read into \c ::x509_buf.
+ * \{
+ */
+#define ASN1_BOOLEAN 0x01
+#define ASN1_INTEGER 0x02
+#define ASN1_BIT_STRING 0x03
+#define ASN1_OCTET_STRING 0x04
+#define ASN1_NULL 0x05
+#define ASN1_OID 0x06
+#define ASN1_UTF8_STRING 0x0C
+#define ASN1_SEQUENCE 0x10
+#define ASN1_SET 0x11
+#define ASN1_PRINTABLE_STRING 0x13
+#define ASN1_T61_STRING 0x14
+#define ASN1_IA5_STRING 0x16
+#define ASN1_UTC_TIME 0x17
+#define ASN1_GENERALIZED_TIME 0x18
+#define ASN1_UNIVERSAL_STRING 0x1C
+#define ASN1_BMP_STRING 0x1E
+#define ASN1_PRIMITIVE 0x00
+#define ASN1_CONSTRUCTED 0x20
+#define ASN1_CONTEXT_SPECIFIC 0x80
+/* \} name */
+/* \} addtogroup asn1_module */
+
+/** Returns the size of the binary string, without the trailing \\0 */
+#define OID_SIZE(x) (sizeof(x) - 1)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name Functions to parse ASN.1 data structures
+ * \{
+ */
+
+/**
+ * Type-length-value structure that allows for ASN1 using DER.
+ */
+typedef struct _asn1_buf
+{
+ int tag; /**< ASN1 type, e.g. ASN1_UTF8_STRING. */
+ size_t len; /**< ASN1 length, e.g. in octets. */
+ unsigned char *p; /**< ASN1 data, e.g. in ASCII. */
+}
+asn1_buf;
+
+/**
+ * Container for ASN1 bit strings.
+ */
+typedef struct _asn1_bitstring
+{
+ size_t len; /**< ASN1 length, e.g. in octets. */
+ unsigned char unused_bits; /**< Number of unused bits at the end of the string */
+ unsigned char *p; /**< Raw ASN1 data for the bit string */
+}
+asn1_bitstring;
+
+/**
+ * Container for a sequence of ASN.1 items
+ */
+typedef struct _asn1_sequence
+{
+ asn1_buf buf; /**< Buffer containing the given ASN.1 item. */
+ struct _asn1_sequence *next; /**< The next entry in the sequence. */
+}
+asn1_sequence;
+
+/**
+ * Get the length of an ASN.1 element.
+ * Updates the pointer to immediately behind the length.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param len The variable that will receive the value
+ *
+ * \return 0 if successful, POLARSSL_ERR_ASN1_OUT_OF_DATA on reaching
+ * end of data, POLARSSL_ERR_ASN1_INVALID_LENGTH if length is
+ * unparseable.
+ */
+int asn1_get_len( unsigned char **p,
+ const unsigned char *end,
+ size_t *len );
+
+/**
+ * Get the tag and length of the tag. Check for the requested tag.
+ * Updates the pointer to immediately behind the tag and length.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param len The variable that will receive the length
+ * \param tag The expected tag
+ *
+ * \return 0 if successful, POLARSSL_ERR_ASN1_UNEXPECTED_TAG if tag did
+ * not match requested tag, or another specific ASN.1 error code.
+ */
+int asn1_get_tag( unsigned char **p,
+ const unsigned char *end,
+ size_t *len, int tag );
+
+/**
+ * Retrieve a boolean ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param val The variable that will receive the value
+ *
+ * \return 0 if successful or a specific ASN.1 error code.
+ */
+int asn1_get_bool( unsigned char **p,
+ const unsigned char *end,
+ int *val );
+
+/**
+ * Retrieve an integer ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param val The variable that will receive the value
+ *
+ * \return 0 if successful or a specific ASN.1 error code.
+ */
+int asn1_get_int( unsigned char **p,
+ const unsigned char *end,
+ int *val );
+
+/**
+ * Retrieve a bitstring ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param bs The variable that will receive the value
+ *
+ * \return 0 if successful or a specific ASN.1 error code.
+ */
+int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
+ asn1_bitstring *bs);
+
+/**
+ * Parses and splits an ASN.1 "SEQUENCE OF "
+ * Updated the pointer to immediately behind the full sequence tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param cur First variable in the chain to fill
+ * \param tag Type of sequence
+ *
+ * \return 0 if successful or a specific ASN.1 error code.
+ */
+int asn1_get_sequence_of( unsigned char **p,
+ const unsigned char *end,
+ asn1_sequence *cur,
+ int tag);
+
+#if defined(POLARSSL_BIGNUM_C)
+/**
+ * Retrieve a MPI value from an integer ASN.1 tag.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param X The MPI that will receive the value
+ *
+ * \return 0 if successful or a specific ASN.1 or MPI error code.
+ */
+int asn1_get_mpi( unsigned char **p,
+ const unsigned char *end,
+ mpi *X );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* asn1.h */
diff --git a/polarssl/asn1parse.c b/polarssl/asn1parse.c
new file mode 100644
index 0000000..2584774
--- /dev/null
+++ b/polarssl/asn1parse.c
@@ -0,0 +1,260 @@
+/*
+ * Generic ASN.1 parsing
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_ASN1_PARSE_C)
+
+#include "polarssl/asn1.h"
+
+#if defined(POLARSSL_BIGNUM_C)
+#include "polarssl/bignum.h"
+#endif
+
+#include
+#include
+#include
+
+/*
+ * ASN.1 DER decoding routines
+ */
+int asn1_get_len( unsigned char **p,
+ const unsigned char *end,
+ size_t *len )
+{
+ if( ( end - *p ) < 1 )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ if( ( **p & 0x80 ) == 0 )
+ *len = *(*p)++;
+ else
+ {
+ switch( **p & 0x7F )
+ {
+ case 1:
+ if( ( end - *p ) < 2 )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ *len = (*p)[1];
+ (*p) += 2;
+ break;
+
+ case 2:
+ if( ( end - *p ) < 3 )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ *len = ( (*p)[1] << 8 ) | (*p)[2];
+ (*p) += 3;
+ break;
+
+ case 3:
+ if( ( end - *p ) < 4 )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ *len = ( (*p)[1] << 16 ) | ( (*p)[2] << 8 ) | (*p)[3];
+ (*p) += 4;
+ break;
+
+ case 4:
+ if( ( end - *p ) < 5 )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ *len = ( (*p)[1] << 24 ) | ( (*p)[2] << 16 ) | ( (*p)[3] << 8 ) | (*p)[4];
+ (*p) += 5;
+ break;
+
+ default:
+ return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
+ }
+ }
+
+ if( *len > (size_t) ( end - *p ) )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ return( 0 );
+}
+
+int asn1_get_tag( unsigned char **p,
+ const unsigned char *end,
+ size_t *len, int tag )
+{
+ if( ( end - *p ) < 1 )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ if( **p != tag )
+ return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+ (*p)++;
+
+ return( asn1_get_len( p, end, len ) );
+}
+
+int asn1_get_bool( unsigned char **p,
+ const unsigned char *end,
+ int *val )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
+ return( ret );
+
+ if( len != 1 )
+ return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+ *val = ( **p != 0 ) ? 1 : 0;
+ (*p)++;
+
+ return( 0 );
+}
+
+int asn1_get_int( unsigned char **p,
+ const unsigned char *end,
+ int *val )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
+ return( ret );
+
+ if( len > sizeof( int ) || ( **p & 0x80 ) != 0 )
+ return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+ *val = 0;
+
+ while( len-- > 0 )
+ {
+ *val = ( *val << 8 ) | **p;
+ (*p)++;
+ }
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_BIGNUM_C)
+int asn1_get_mpi( unsigned char **p,
+ const unsigned char *end,
+ mpi *X )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
+ return( ret );
+
+ ret = mpi_read_binary( X, *p, len );
+
+ *p += len;
+
+ return( ret );
+}
+#endif /* POLARSSL_BIGNUM_C */
+
+int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
+ asn1_bitstring *bs)
+{
+ int ret;
+
+ /* Certificate type is a single byte bitstring */
+ if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 )
+ return( ret );
+
+ /* Check length, subtract one for actual bit string length */
+ if ( bs->len < 1 )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+ bs->len -= 1;
+
+ /* Get number of unused bits, ensure unused bits <= 7 */
+ bs->unused_bits = **p;
+ if( bs->unused_bits > 7 )
+ return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
+ (*p)++;
+
+ /* Get actual bitstring */
+ bs->p = *p;
+ *p += bs->len;
+
+ if( *p != end )
+ return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return 0;
+}
+
+
+/*
+ * Parses and splits an ASN.1 "SEQUENCE OF "
+ */
+int asn1_get_sequence_of( unsigned char **p,
+ const unsigned char *end,
+ asn1_sequence *cur,
+ int tag)
+{
+ int ret;
+ size_t len;
+ asn1_buf *buf;
+
+ /* Get main sequence tag */
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ return( ret );
+
+ if( *p + len != end )
+ return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ while( *p < end )
+ {
+ buf = &(cur->buf);
+ buf->tag = **p;
+
+ if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
+ return( ret );
+
+ buf->p = *p;
+ *p += buf->len;
+
+ /* Allocate and assign next pointer */
+ if (*p < end)
+ {
+ cur->next = (asn1_sequence *) malloc(
+ sizeof( asn1_sequence ) );
+
+ if( cur->next == NULL )
+ return( POLARSSL_ERR_ASN1_MALLOC_FAILED );
+
+ cur = cur->next;
+ }
+ }
+
+ /* Set final sequence entry's next pointer to NULL */
+ cur->next = NULL;
+
+ if( *p != end )
+ return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+#endif
diff --git a/polarssl/asn1write.c b/polarssl/asn1write.c
new file mode 100644
index 0000000..e50c17c
--- /dev/null
+++ b/polarssl/asn1write.c
@@ -0,0 +1,241 @@
+/*
+ * ASN.1 buffer writing functionality
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_ASN1_WRITE_C)
+
+#include "polarssl/asn1write.h"
+
+int asn1_write_len( unsigned char **p, unsigned char *start, size_t len )
+{
+ if( len < 0x80 )
+ {
+ if( *p - start < 1 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = len;
+ return( 1 );
+ }
+
+ if( len <= 0xFF )
+ {
+ if( *p - start < 2 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = len;
+ *--(*p) = 0x81;
+ return( 2 );
+ }
+
+ if( *p - start < 3 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ // We assume we never have lengths larger than 65535 bytes
+ //
+ *--(*p) = len % 256;
+ *--(*p) = ( len / 256 ) % 256;
+ *--(*p) = 0x82;
+
+ return( 3 );
+}
+
+int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
+{
+ if( *p - start < 1 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = tag;
+
+ return( 1 );
+}
+
+int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X )
+{
+ int ret;
+ size_t len = 0;
+
+ // Write the MPI
+ //
+ len = mpi_size( X );
+
+ if( *p - start < (int) len )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ (*p) -= len;
+ mpi_write_binary( X, *p, len );
+
+ // DER format assumes 2s complement for numbers, so the leftmost bit
+ // should be 0 for positive numbers and 1 for negative numbers.
+ //
+ if ( X->s ==1 && **p & 0x80 )
+ {
+ if( *p - start < 1 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = 0x00;
+ len += 1;
+ }
+
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) );
+
+ return( len );
+}
+
+int asn1_write_null( unsigned char **p, unsigned char *start )
+{
+ int ret;
+ size_t len = 0;
+
+ // Write NULL
+ //
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, 0) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_NULL ) );
+
+ return( len );
+}
+
+int asn1_write_oid( unsigned char **p, unsigned char *start, char *oid )
+{
+ int ret;
+ size_t len = 0;
+
+ // Write OID
+ //
+ len = strlen( oid );
+
+ if( *p - start < (int) len )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ (*p) -= len;
+ memcpy( *p, oid, len );
+
+ ASN1_CHK_ADD( len , asn1_write_len( p, start, len ) );
+ ASN1_CHK_ADD( len , asn1_write_tag( p, start, ASN1_OID ) );
+
+ return( len );
+}
+
+int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
+ char *algorithm_oid )
+{
+ int ret;
+ size_t null_len = 0;
+ size_t oid_len = 0;
+ size_t len = 0;
+
+ // Write NULL
+ //
+ ASN1_CHK_ADD( null_len, asn1_write_null( p, start ) );
+
+ // Write OID
+ //
+ ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, algorithm_oid ) );
+
+ len = oid_len + null_len;
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, oid_len + null_len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+ return( len );
+}
+
+int asn1_write_int( unsigned char **p, unsigned char *start, int val )
+{
+ int ret;
+ size_t len = 0;
+
+ // TODO negative values and values larger than 128
+ // DER format assumes 2s complement for numbers, so the leftmost bit
+ // should be 0 for positive numbers and 1 for negative numbers.
+ //
+ if( *p - start < 1 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ len += 1;
+ *--(*p) = val;
+
+ if ( val > 0 && **p & 0x80 )
+ {
+ if( *p - start < 1 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = 0x00;
+ len += 1;
+ }
+
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) );
+
+ return( len );
+}
+
+int asn1_write_printable_string( unsigned char **p, unsigned char *start,
+ char *text )
+{
+ int ret;
+ size_t len = 0;
+
+ // Write string
+ //
+ len = strlen( text );
+
+ if( *p - start < (int) len )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ (*p) -= len;
+ memcpy( *p, text, len );
+
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_PRINTABLE_STRING ) );
+
+ return( len );
+}
+
+int asn1_write_ia5_string( unsigned char **p, unsigned char *start,
+ char *text )
+{
+ int ret;
+ size_t len = 0;
+
+ // Write string
+ //
+ len = strlen( text );
+
+ if( *p - start < (int) len )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ (*p) -= len;
+ memcpy( *p, text, len );
+
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_IA5_STRING ) );
+
+ return( len );
+}
+
+
+#endif
diff --git a/polarssl/asn1write.h b/polarssl/asn1write.h
new file mode 100644
index 0000000..7ea2680
--- /dev/null
+++ b/polarssl/asn1write.h
@@ -0,0 +1,46 @@
+/**
+ * \file asn1write.h
+ *
+ * \brief ASN.1 buffer writing functionality
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ASN1_WRITE_H
+#define POLARSSL_ASN1_WRITE_H
+
+#include "polarssl/asn1.h"
+
+#define ASN1_CHK_ADD(g, f) if( ( ret = f ) < 0 ) return( ret ); else g += ret
+
+int asn1_write_len( unsigned char **p, unsigned char *start, size_t len );
+int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag );
+int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X );
+int asn1_write_null( unsigned char **p, unsigned char *start );
+int asn1_write_oid( unsigned char **p, unsigned char *start, char *oid );
+int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, char *algorithm_oid );
+int asn1_write_int( unsigned char **p, unsigned char *start, int val );
+int asn1_write_printable_string( unsigned char **p, unsigned char *start,
+ char *text );
+int asn1_write_ia5_string( unsigned char **p, unsigned char *start,
+ char *text );
+
+#endif /* POLARSSL_ASN1_WRITE_H */
diff --git a/polarssl/base64.c b/polarssl/base64.c
new file mode 100644
index 0000000..f320f3c
--- /dev/null
+++ b/polarssl/base64.c
@@ -0,0 +1,269 @@
+/*
+ * RFC 1521 base64 encoding/decoding
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_BASE64_C)
+
+#include "polarssl/base64.h"
+
+#ifdef _MSC_VER
+#include
+typedef UINT32 uint32_t;
+#else
+#include
+#endif
+
+static const unsigned char base64_enc_map[64] =
+{
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+ 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', '+', '/'
+};
+
+static const unsigned char base64_dec_map[128] =
+{
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
+ 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 127, 127, 127, 127, 127
+};
+
+/*
+ * Encode a buffer into base64 format
+ */
+int base64_encode( unsigned char *dst, size_t *dlen,
+ const unsigned char *src, size_t slen )
+{
+ size_t i, n;
+ int C1, C2, C3;
+ unsigned char *p;
+
+ if( slen == 0 )
+ return( 0 );
+
+ n = (slen << 3) / 6;
+
+ switch( (slen << 3) - (n * 6) )
+ {
+ case 2: n += 3; break;
+ case 4: n += 2; break;
+ default: break;
+ }
+
+ if( *dlen < n + 1 )
+ {
+ *dlen = n + 1;
+ return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
+ }
+
+ n = (slen / 3) * 3;
+
+ for( i = 0, p = dst; i < n; i += 3 )
+ {
+ C1 = *src++;
+ C2 = *src++;
+ C3 = *src++;
+
+ *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+ *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+ *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
+ *p++ = base64_enc_map[C3 & 0x3F];
+ }
+
+ if( i < slen )
+ {
+ C1 = *src++;
+ C2 = ((i + 1) < slen) ? *src++ : 0;
+
+ *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+ *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+
+ if( (i + 1) < slen )
+ *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
+ else *p++ = '=';
+
+ *p++ = '=';
+ }
+
+ *dlen = p - dst;
+ *p = 0;
+
+ return( 0 );
+}
+
+/*
+ * Decode a base64-formatted buffer
+ */
+int base64_decode( unsigned char *dst, size_t *dlen,
+ const unsigned char *src, size_t slen )
+{
+ size_t i, n;
+ uint32_t j, x;
+ unsigned char *p;
+
+ for( i = j = n = 0; i < slen; i++ )
+ {
+ if( ( slen - i ) >= 2 &&
+ src[i] == '\r' && src[i + 1] == '\n' )
+ continue;
+
+ if( src[i] == '\n' )
+ continue;
+
+ if( src[i] == '=' && ++j > 2 ){
+ printf("err 0 char[%d] = '%c' (0x%x)\n",i,src[i],src[i]);
+ return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+ }
+
+ if( src[i] > 127 || base64_dec_map[src[i]] == 127 ){
+ printf("err 1 char[%d] = '%c' (0x%x)\n",i,src[i],src[i]);
+ return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+ }
+
+ if( base64_dec_map[src[i]] < 64 && j != 0 ){
+ printf("err 2 char[%d] = '%c' (0x%x)\n",i,src[i],src[i]);
+ return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+ }
+
+ n++;
+ }
+
+ if( n == 0 )
+ return( 0 );
+
+
+ n = ((n * 6) + 7) >> 3;
+
+ if( (*dlen+4) < n )
+ {
+ *dlen = n;
+ return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
+ }
+
+ for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
+ {
+ if( *src == '\r' || *src == '\n' )
+ continue;
+
+ j -= ( base64_dec_map[*src] == 64 );
+ x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
+
+ if( ++n == 4 )
+ {
+ n = 0;
+ if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
+ if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
+ if( j > 2 ) *p++ = (unsigned char)( x );
+ }
+ }
+
+ *dlen = p - dst;
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include
+#include
+
+static const unsigned char base64_test_dec[64] =
+{
+ 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
+ 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
+ 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
+ 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
+ 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
+ 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
+ 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
+ 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
+};
+
+static const unsigned char base64_test_enc[] =
+ "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
+ "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
+
+/*
+ * Checkup routine
+ */
+int base64_self_test( int verbose )
+{
+ size_t len;
+ const unsigned char *src;
+ unsigned char buffer[128];
+
+ if( verbose != 0 )
+ printf( " Base64 encoding test: " );
+
+ len = sizeof( buffer );
+ src = base64_test_dec;
+
+ if( base64_encode( buffer, &len, src, 64 ) != 0 ||
+ memcmp( base64_test_enc, buffer, 88 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n Base64 decoding test: " );
+
+ len = sizeof( buffer );
+ src = base64_test_enc;
+
+ if( base64_decode( buffer, &len, src, 88 ) != 0 ||
+ memcmp( base64_test_dec, buffer, 64 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/base64.h b/polarssl/base64.h
new file mode 100644
index 0000000..fb0d753
--- /dev/null
+++ b/polarssl/base64.h
@@ -0,0 +1,87 @@
+/**
+ * \file base64.h
+ *
+ * \brief RFC 1521 base64 encoding/decoding
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_BASE64_H
+#define POLARSSL_BASE64_H
+
+#include
+
+#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */
+#define POLARSSL_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Encode a buffer into base64 format
+ *
+ * \param dst destination buffer
+ * \param dlen size of the buffer
+ * \param src source buffer
+ * \param slen amount of data to be encoded
+ *
+ * \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL.
+ * *dlen is always updated to reflect the amount
+ * of data that has (or would have) been written.
+ *
+ * \note Call this function with *dlen = 0 to obtain the
+ * required buffer size in *dlen
+ */
+int base64_encode( unsigned char *dst, size_t *dlen,
+ const unsigned char *src, size_t slen );
+
+/**
+ * \brief Decode a base64-formatted buffer
+ *
+ * \param dst destination buffer
+ * \param dlen size of the buffer
+ * \param src source buffer
+ * \param slen amount of data to be decoded
+ *
+ * \return 0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or
+ * POLARSSL_ERR_BASE64_INVALID_CHARACTER if the input data is
+ * not correct. *dlen is always updated to reflect the amount
+ * of data that has (or would have) been written.
+ *
+ * \note Call this function with *dlen = 0 to obtain the
+ * required buffer size in *dlen
+ */
+int base64_decode( unsigned char *dst, size_t *dlen,
+ const unsigned char *src, size_t slen );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int base64_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* base64.h */
diff --git a/polarssl/bignum.c b/polarssl/bignum.c
new file mode 100644
index 0000000..5c8f96c
--- /dev/null
+++ b/polarssl/bignum.c
@@ -0,0 +1,2135 @@
+/*
+ * Multi-precision integer library
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * This MPI implementation is based on:
+ *
+ * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
+ * http://www.stillhq.com/extracted/gnupg-api/mpi/
+ * http://math.libtomcrypt.com/files/tommath.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_BIGNUM_C)
+
+#include "polarssl/bignum.h"
+#include "polarssl/bn_mul.h"
+
+#include
+
+#define ciL (sizeof(t_uint)) /* chars in limb */
+#define biL (ciL << 3) /* bits in limb */
+#define biH (ciL << 2) /* half limb size */
+
+/*
+ * Convert between bits/chars and number of limbs
+ */
+#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
+#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
+
+/*
+ * Initialize one MPI
+ */
+void mpi_init( mpi *X )
+{
+ if( X == NULL )
+ return;
+
+ X->s = 1;
+ X->n = 0;
+ X->p = NULL;
+}
+
+/*
+ * Unallocate one MPI
+ */
+void mpi_free( mpi *X )
+{
+ if( X == NULL )
+ return;
+
+ if( X->p != NULL )
+ {
+ memset( X->p, 0, X->n * ciL );
+ free( X->p );
+ }
+
+ X->s = 1;
+ X->n = 0;
+ X->p = NULL;
+}
+
+/*
+ * Enlarge to the specified number of limbs
+ */
+int mpi_grow( mpi *X, size_t nblimbs )
+{
+ t_uint *p;
+
+ if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
+ return( POLARSSL_ERR_MPI_MALLOC_FAILED );
+
+ if( X->n < nblimbs )
+ {
+ if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL )
+ return( POLARSSL_ERR_MPI_MALLOC_FAILED );
+
+ memset( p, 0, nblimbs * ciL );
+
+ if( X->p != NULL )
+ {
+ memcpy( p, X->p, X->n * ciL );
+ memset( X->p, 0, X->n * ciL );
+ free( X->p );
+ }
+
+ X->n = nblimbs;
+ X->p = p;
+ }
+
+ return( 0 );
+}
+
+/*
+ * Copy the contents of Y into X
+ */
+int mpi_copy( mpi *X, const mpi *Y )
+{
+ int ret;
+ size_t i;
+
+ if( X == Y )
+ return( 0 );
+
+ for( i = Y->n - 1; i > 0; i-- )
+ if( Y->p[i] != 0 )
+ break;
+ i++;
+
+ X->s = Y->s;
+
+ MPI_CHK( mpi_grow( X, i ) );
+
+ memset( X->p, 0, X->n * ciL );
+ memcpy( X->p, Y->p, i * ciL );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Swap the contents of X and Y
+ */
+void mpi_swap( mpi *X, mpi *Y )
+{
+ mpi T;
+
+ memcpy( &T, X, sizeof( mpi ) );
+ memcpy( X, Y, sizeof( mpi ) );
+ memcpy( Y, &T, sizeof( mpi ) );
+}
+
+/*
+ * Set value from integer
+ */
+int mpi_lset( mpi *X, t_sint z )
+{
+ int ret;
+
+ MPI_CHK( mpi_grow( X, 1 ) );
+ memset( X->p, 0, X->n * ciL );
+
+ X->p[0] = ( z < 0 ) ? -z : z;
+ X->s = ( z < 0 ) ? -1 : 1;
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Get a specific bit
+ */
+int mpi_get_bit( const mpi *X, size_t pos )
+{
+ if( X->n * biL <= pos )
+ return( 0 );
+
+ return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
+}
+
+/*
+ * Set a bit to a specific value of 0 or 1
+ */
+int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
+{
+ int ret = 0;
+ size_t off = pos / biL;
+ size_t idx = pos % biL;
+
+ if( val != 0 && val != 1 )
+ return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
+
+ if( X->n * biL <= pos )
+ {
+ if( val == 0 )
+ return ( 0 );
+
+ MPI_CHK( mpi_grow( X, off + 1 ) );
+ }
+
+ X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Return the number of least significant bits
+ */
+size_t mpi_lsb( const mpi *X )
+{
+ size_t i, j, count = 0;
+
+ for( i = 0; i < X->n; i++ )
+ for( j = 0; j < biL; j++, count++ )
+ if( ( ( X->p[i] >> j ) & 1 ) != 0 )
+ return( count );
+
+ return( 0 );
+}
+
+/*
+ * Return the number of most significant bits
+ */
+size_t mpi_msb( const mpi *X )
+{
+ size_t i, j;
+
+ for( i = X->n - 1; i > 0; i-- )
+ if( X->p[i] != 0 )
+ break;
+
+ for( j = biL; j > 0; j-- )
+ if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
+ break;
+
+ return( ( i * biL ) + j );
+}
+
+/*
+ * Return the total size in bytes
+ */
+size_t mpi_size( const mpi *X )
+{
+ return( ( mpi_msb( X ) + 7 ) >> 3 );
+}
+
+/*
+ * Convert an ASCII character to digit value
+ */
+static int mpi_get_digit( t_uint *d, int radix, char c )
+{
+ *d = 255;
+
+ if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
+ if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
+ if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
+
+ if( *d >= (t_uint) radix )
+ return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
+
+ return( 0 );
+}
+
+/*
+ * Import from an ASCII string
+ */
+int mpi_read_string( mpi *X, int radix, const char *s )
+{
+ int ret;
+ size_t i, j, slen, n;
+ t_uint d;
+ mpi T;
+
+ if( radix < 2 || radix > 16 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ mpi_init( &T );
+
+ slen = strlen( s );
+
+ if( radix == 16 )
+ {
+ n = BITS_TO_LIMBS( slen << 2 );
+
+ MPI_CHK( mpi_grow( X, n ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i = slen, j = 0; i > 0; i--, j++ )
+ {
+ if( i == 1 && s[i - 1] == '-' )
+ {
+ X->s = -1;
+ break;
+ }
+
+ MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
+ X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i = 0; i < slen; i++ )
+ {
+ if( i == 0 && s[i] == '-' )
+ {
+ X->s = -1;
+ continue;
+ }
+
+ MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
+ MPI_CHK( mpi_mul_int( &T, X, radix ) );
+
+ if( X->s == 1 )
+ {
+ MPI_CHK( mpi_add_int( X, &T, d ) );
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_int( X, &T, d ) );
+ }
+ }
+ }
+
+cleanup:
+
+ mpi_free( &T );
+
+ return( ret );
+}
+
+/*
+ * Helper to write the digits high-order first
+ */
+static int mpi_write_hlp( mpi *X, int radix, char **p )
+{
+ int ret;
+ t_uint r;
+
+ if( radix < 2 || radix > 16 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ MPI_CHK( mpi_mod_int( &r, X, radix ) );
+ MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
+
+ if( mpi_cmp_int( X, 0 ) != 0 )
+ MPI_CHK( mpi_write_hlp( X, radix, p ) );
+
+ if( r < 10 )
+ *(*p)++ = (char)( r + 0x30 );
+ else
+ *(*p)++ = (char)( r + 0x37 );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Export into an ASCII string
+ */
+int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
+{
+ int ret = 0;
+ size_t n;
+ char *p;
+ mpi T;
+
+ if( radix < 2 || radix > 16 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ n = mpi_msb( X );
+ if( radix >= 4 ) n >>= 1;
+ if( radix >= 16 ) n >>= 1;
+ n += 3;
+
+ if( *slen < n )
+ {
+ *slen = n;
+ return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+ }
+
+ p = s;
+ mpi_init( &T );
+
+ if( X->s == -1 )
+ *p++ = '-';
+
+ if( radix == 16 )
+ {
+ int c;
+ size_t i, j, k;
+
+ for( i = X->n, k = 0; i > 0; i-- )
+ {
+ for( j = ciL; j > 0; j-- )
+ {
+ c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
+
+ if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
+ continue;
+
+ *(p++) = "0123456789ABCDEF" [c / 16];
+ *(p++) = "0123456789ABCDEF" [c % 16];
+ k = 1;
+ }
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_copy( &T, X ) );
+
+ if( T.s == -1 )
+ T.s = 1;
+
+ MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
+ }
+
+ *p++ = '\0';
+ *slen = p - s;
+
+cleanup:
+
+ mpi_free( &T );
+
+ return( ret );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Read X from an opened file
+ */
+int mpi_read_file( mpi *X, int radix, FILE *fin )
+{
+ t_uint d;
+ size_t slen;
+ char *p;
+ /*
+ * Buffer should have space for (short) label and decimal formatted MPI,
+ * newline characters and '\0'
+ */
+ char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
+
+ memset( s, 0, sizeof( s ) );
+ if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
+ return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
+
+ slen = strlen( s );
+ if( slen == sizeof( s ) - 2 )
+ return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+
+ if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
+ if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
+
+ p = s + slen;
+ while( --p >= s )
+ if( mpi_get_digit( &d, radix, *p ) != 0 )
+ break;
+
+ return( mpi_read_string( X, radix, p + 1 ) );
+}
+
+/*
+ * Write X into an opened file (or stdout if fout == NULL)
+ */
+int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
+{
+ int ret;
+ size_t n, slen, plen;
+ /*
+ * Buffer should have space for (short) label and decimal formatted MPI,
+ * newline characters and '\0'
+ */
+ char s[ POLARSSL_MPI_RW_BUFFER_SIZE ];
+
+ n = sizeof( s );
+ memset( s, 0, n );
+ n -= 2;
+
+ MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
+
+ if( p == NULL ) p = "";
+
+ plen = strlen( p );
+ slen = strlen( s );
+ s[slen++] = '\r';
+ s[slen++] = '\n';
+
+ if( fout != NULL )
+ {
+ if( fwrite( p, 1, plen, fout ) != plen ||
+ fwrite( s, 1, slen, fout ) != slen )
+ return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
+ }
+ else
+ printf( "%s%s", p, s );
+
+cleanup:
+
+ return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * Import X from unsigned binary data, big endian
+ */
+int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
+{
+ int ret;
+ size_t i, j, n;
+
+ for( n = 0; n < buflen; n++ )
+ if( buf[n] != 0 )
+ break;
+
+ MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i = buflen, j = 0; i > n; i--, j++ )
+ X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Export X into unsigned binary data, big endian
+ */
+int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
+{
+ size_t i, j, n;
+
+ n = mpi_size( X );
+
+ if( buflen < n )
+ return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+
+ memset( buf, 0, buflen );
+
+ for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
+ buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
+
+ return( 0 );
+}
+
+/*
+ * Left-shift: X <<= count
+ */
+int mpi_shift_l( mpi *X, size_t count )
+{
+ int ret;
+ size_t i, v0, t1;
+ t_uint r0 = 0, r1;
+
+ v0 = count / (biL );
+ t1 = count & (biL - 1);
+
+ i = mpi_msb( X ) + count;
+
+ if( X->n * biL < i )
+ MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
+
+ ret = 0;
+
+ /*
+ * shift by count / limb_size
+ */
+ if( v0 > 0 )
+ {
+ for( i = X->n; i > v0; i-- )
+ X->p[i - 1] = X->p[i - v0 - 1];
+
+ for( ; i > 0; i-- )
+ X->p[i - 1] = 0;
+ }
+
+ /*
+ * shift by count % limb_size
+ */
+ if( t1 > 0 )
+ {
+ for( i = v0; i < X->n; i++ )
+ {
+ r1 = X->p[i] >> (biL - t1);
+ X->p[i] <<= t1;
+ X->p[i] |= r0;
+ r0 = r1;
+ }
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Right-shift: X >>= count
+ */
+int mpi_shift_r( mpi *X, size_t count )
+{
+ size_t i, v0, v1;
+ t_uint r0 = 0, r1;
+
+ v0 = count / biL;
+ v1 = count & (biL - 1);
+
+ if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
+ return mpi_lset( X, 0 );
+
+ /*
+ * shift by count / limb_size
+ */
+ if( v0 > 0 )
+ {
+ for( i = 0; i < X->n - v0; i++ )
+ X->p[i] = X->p[i + v0];
+
+ for( ; i < X->n; i++ )
+ X->p[i] = 0;
+ }
+
+ /*
+ * shift by count % limb_size
+ */
+ if( v1 > 0 )
+ {
+ for( i = X->n; i > 0; i-- )
+ {
+ r1 = X->p[i - 1] << (biL - v1);
+ X->p[i - 1] >>= v1;
+ X->p[i - 1] |= r0;
+ r0 = r1;
+ }
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare unsigned values
+ */
+int mpi_cmp_abs( const mpi *X, const mpi *Y )
+{
+ size_t i, j;
+
+ for( i = X->n; i > 0; i-- )
+ if( X->p[i - 1] != 0 )
+ break;
+
+ for( j = Y->n; j > 0; j-- )
+ if( Y->p[j - 1] != 0 )
+ break;
+
+ if( i == 0 && j == 0 )
+ return( 0 );
+
+ if( i > j ) return( 1 );
+ if( j > i ) return( -1 );
+
+ for( ; i > 0; i-- )
+ {
+ if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
+ if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_mpi( const mpi *X, const mpi *Y )
+{
+ size_t i, j;
+
+ for( i = X->n; i > 0; i-- )
+ if( X->p[i - 1] != 0 )
+ break;
+
+ for( j = Y->n; j > 0; j-- )
+ if( Y->p[j - 1] != 0 )
+ break;
+
+ if( i == 0 && j == 0 )
+ return( 0 );
+
+ if( i > j ) return( X->s );
+ if( j > i ) return( -Y->s );
+
+ if( X->s > 0 && Y->s < 0 ) return( 1 );
+ if( Y->s > 0 && X->s < 0 ) return( -1 );
+
+ for( ; i > 0; i-- )
+ {
+ if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
+ if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_int( const mpi *X, t_sint z )
+{
+ mpi Y;
+ t_uint p[1];
+
+ *p = ( z < 0 ) ? -z : z;
+ Y.s = ( z < 0 ) ? -1 : 1;
+ Y.n = 1;
+ Y.p = p;
+
+ return( mpi_cmp_mpi( X, &Y ) );
+}
+
+/*
+ * Unsigned addition: X = |A| + |B| (HAC 14.7)
+ */
+int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t i, j;
+ t_uint *o, *p, c;
+
+ if( X == B )
+ {
+ const mpi *T = A; A = X; B = T;
+ }
+
+ if( X != A )
+ MPI_CHK( mpi_copy( X, A ) );
+
+ /*
+ * X should always be positive as a result of unsigned additions.
+ */
+ X->s = 1;
+
+ for( j = B->n; j > 0; j-- )
+ if( B->p[j - 1] != 0 )
+ break;
+
+ MPI_CHK( mpi_grow( X, j ) );
+
+ o = B->p; p = X->p; c = 0;
+
+ for( i = 0; i < j; i++, o++, p++ )
+ {
+ *p += c; c = ( *p < c );
+ *p += *o; c += ( *p < *o );
+ }
+
+ while( c != 0 )
+ {
+ if( i >= X->n )
+ {
+ MPI_CHK( mpi_grow( X, i + 1 ) );
+ p = X->p + i;
+ }
+
+ *p += c; c = ( *p < c ); i++; p++;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Helper for mpi substraction
+ */
+static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
+{
+ size_t i;
+ t_uint c, z;
+
+ for( i = c = 0; i < n; i++, s++, d++ )
+ {
+ z = ( *d < c ); *d -= c;
+ c = ( *d < *s ) + z; *d -= *s;
+ }
+
+ while( c != 0 )
+ {
+ z = ( *d < c ); *d -= c;
+ c = z; i++; d++;
+ }
+}
+
+/*
+ * Unsigned substraction: X = |A| - |B| (HAC 14.9)
+ */
+int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
+{
+ mpi TB;
+ int ret;
+ size_t n;
+
+ if( mpi_cmp_abs( A, B ) < 0 )
+ return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
+
+ mpi_init( &TB );
+
+ if( X == B )
+ {
+ MPI_CHK( mpi_copy( &TB, B ) );
+ B = &TB;
+ }
+
+ if( X != A )
+ MPI_CHK( mpi_copy( X, A ) );
+
+ /*
+ * X should always be positive as a result of unsigned substractions.
+ */
+ X->s = 1;
+
+ ret = 0;
+
+ for( n = B->n; n > 0; n-- )
+ if( B->p[n - 1] != 0 )
+ break;
+
+ mpi_sub_hlp( n, B->p, X->p );
+
+cleanup:
+
+ mpi_free( &TB );
+
+ return( ret );
+}
+
+/*
+ * Signed addition: X = A + B
+ */
+int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret, s = A->s;
+
+ if( A->s * B->s < 0 )
+ {
+ if( mpi_cmp_abs( A, B ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_abs( X, A, B ) );
+ X->s = s;
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_abs( X, B, A ) );
+ X->s = -s;
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_add_abs( X, A, B ) );
+ X->s = s;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Signed substraction: X = A - B
+ */
+int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret, s = A->s;
+
+ if( A->s * B->s > 0 )
+ {
+ if( mpi_cmp_abs( A, B ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_abs( X, A, B ) );
+ X->s = s;
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_abs( X, B, A ) );
+ X->s = -s;
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_add_abs( X, A, B ) );
+ X->s = s;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Signed addition: X = A + b
+ */
+int mpi_add_int( mpi *X, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mpi_add_mpi( X, A, &_B ) );
+}
+
+/*
+ * Signed substraction: X = A - b
+ */
+int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mpi_sub_mpi( X, A, &_B ) );
+}
+
+/*
+ * Helper for mpi multiplication
+ */
+static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
+{
+ t_uint c = 0, t = 0;
+
+#if defined(MULADDC_HUIT)
+ for( ; i >= 8; i -= 8 )
+ {
+ MULADDC_INIT
+ MULADDC_HUIT
+ MULADDC_STOP
+ }
+
+ for( ; i > 0; i-- )
+ {
+ MULADDC_INIT
+ MULADDC_CORE
+ MULADDC_STOP
+ }
+#else
+ for( ; i >= 16; i -= 16 )
+ {
+ MULADDC_INIT
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_STOP
+ }
+
+ for( ; i >= 8; i -= 8 )
+ {
+ MULADDC_INIT
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_STOP
+ }
+
+ for( ; i > 0; i-- )
+ {
+ MULADDC_INIT
+ MULADDC_CORE
+ MULADDC_STOP
+ }
+#endif
+
+ t++;
+
+ do {
+ *d += c; c = ( *d < c ); d++;
+ }
+ while( c != 0 );
+}
+
+/*
+ * Baseline multiplication: X = A * B (HAC 14.12)
+ */
+int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t i, j;
+ mpi TA, TB;
+
+ mpi_init( &TA ); mpi_init( &TB );
+
+ if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
+ if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
+
+ for( i = A->n; i > 0; i-- )
+ if( A->p[i - 1] != 0 )
+ break;
+
+ for( j = B->n; j > 0; j-- )
+ if( B->p[j - 1] != 0 )
+ break;
+
+ MPI_CHK( mpi_grow( X, i + j ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i++; j > 0; j-- )
+ mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
+
+ X->s = A->s * B->s;
+
+cleanup:
+
+ mpi_free( &TB ); mpi_free( &TA );
+
+ return( ret );
+}
+
+/*
+ * Baseline multiplication: X = A * b
+ */
+int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ _B.s = 1;
+ _B.n = 1;
+ _B.p = p;
+ p[0] = b;
+
+ return( mpi_mul_mpi( X, A, &_B ) );
+}
+
+/*
+ * Division by mpi: A = Q * B + R (HAC 14.20)
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t i, n, t, k;
+ mpi X, Y, Z, T1, T2;
+
+ if( mpi_cmp_int( B, 0 ) == 0 )
+ return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+ mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
+ mpi_init( &T1 ); mpi_init( &T2 );
+
+ if( mpi_cmp_abs( A, B ) < 0 )
+ {
+ if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
+ if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
+ return( 0 );
+ }
+
+ MPI_CHK( mpi_copy( &X, A ) );
+ MPI_CHK( mpi_copy( &Y, B ) );
+ X.s = Y.s = 1;
+
+ MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
+ MPI_CHK( mpi_lset( &Z, 0 ) );
+ MPI_CHK( mpi_grow( &T1, 2 ) );
+ MPI_CHK( mpi_grow( &T2, 3 ) );
+
+ k = mpi_msb( &Y ) % biL;
+ if( k < biL - 1 )
+ {
+ k = biL - 1 - k;
+ MPI_CHK( mpi_shift_l( &X, k ) );
+ MPI_CHK( mpi_shift_l( &Y, k ) );
+ }
+ else k = 0;
+
+ n = X.n - 1;
+ t = Y.n - 1;
+ MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
+
+ while( mpi_cmp_mpi( &X, &Y ) >= 0 )
+ {
+ Z.p[n - t]++;
+ mpi_sub_mpi( &X, &X, &Y );
+ }
+ mpi_shift_r( &Y, biL * (n - t) );
+
+ for( i = n; i > t ; i-- )
+ {
+ if( X.p[i] >= Y.p[t] )
+ Z.p[i - t - 1] = ~0;
+ else
+ {
+#if defined(POLARSSL_HAVE_UDBL)
+ t_udbl r;
+
+ r = (t_udbl) X.p[i] << biL;
+ r |= (t_udbl) X.p[i - 1];
+ r /= Y.p[t];
+ if( r > ((t_udbl) 1 << biL) - 1)
+ r = ((t_udbl) 1 << biL) - 1;
+
+ Z.p[i - t - 1] = (t_uint) r;
+#else
+ /*
+ * __udiv_qrnnd_c, from gmp/longlong.h
+ */
+ t_uint q0, q1, r0, r1;
+ t_uint d0, d1, d, m;
+
+ d = Y.p[t];
+ d0 = ( d << biH ) >> biH;
+ d1 = ( d >> biH );
+
+ q1 = X.p[i] / d1;
+ r1 = X.p[i] - d1 * q1;
+ r1 <<= biH;
+ r1 |= ( X.p[i - 1] >> biH );
+
+ m = q1 * d0;
+ if( r1 < m )
+ {
+ q1--, r1 += d;
+ while( r1 >= d && r1 < m )
+ q1--, r1 += d;
+ }
+ r1 -= m;
+
+ q0 = r1 / d1;
+ r0 = r1 - d1 * q0;
+ r0 <<= biH;
+ r0 |= ( X.p[i - 1] << biH ) >> biH;
+
+ m = q0 * d0;
+ if( r0 < m )
+ {
+ q0--, r0 += d;
+ while( r0 >= d && r0 < m )
+ q0--, r0 += d;
+ }
+ r0 -= m;
+
+ Z.p[i - t - 1] = ( q1 << biH ) | q0;
+#endif
+ }
+
+ Z.p[i - t - 1]++;
+ do
+ {
+ Z.p[i - t - 1]--;
+
+ MPI_CHK( mpi_lset( &T1, 0 ) );
+ T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
+ T1.p[1] = Y.p[t];
+ MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
+
+ MPI_CHK( mpi_lset( &T2, 0 ) );
+ T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
+ T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
+ T2.p[2] = X.p[i];
+ }
+ while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
+
+ MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
+ MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
+ MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
+
+ if( mpi_cmp_int( &X, 0 ) < 0 )
+ {
+ MPI_CHK( mpi_copy( &T1, &Y ) );
+ MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
+ MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
+ Z.p[i - t - 1]--;
+ }
+ }
+
+ if( Q != NULL )
+ {
+ mpi_copy( Q, &Z );
+ Q->s = A->s * B->s;
+ }
+
+ if( R != NULL )
+ {
+ mpi_shift_r( &X, k );
+ X.s = A->s;
+ mpi_copy( R, &X );
+
+ if( mpi_cmp_int( R, 0 ) == 0 )
+ R->s = 1;
+ }
+
+cleanup:
+
+ mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
+ mpi_free( &T1 ); mpi_free( &T2 );
+
+ return( ret );
+}
+
+/*
+ * Division by int: A = Q * b + R
+ */
+int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mpi_div_mpi( Q, R, A, &_B ) );
+}
+
+/*
+ * Modulo: R = A mod B
+ */
+int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
+{
+ int ret;
+
+ if( mpi_cmp_int( B, 0 ) < 0 )
+ return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+
+ MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
+
+ while( mpi_cmp_int( R, 0 ) < 0 )
+ MPI_CHK( mpi_add_mpi( R, R, B ) );
+
+ while( mpi_cmp_mpi( R, B ) >= 0 )
+ MPI_CHK( mpi_sub_mpi( R, R, B ) );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Modulo: r = A mod b
+ */
+int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
+{
+ size_t i;
+ t_uint x, y, z;
+
+ if( b == 0 )
+ return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+ if( b < 0 )
+ return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+
+ /*
+ * handle trivial cases
+ */
+ if( b == 1 )
+ {
+ *r = 0;
+ return( 0 );
+ }
+
+ if( b == 2 )
+ {
+ *r = A->p[0] & 1;
+ return( 0 );
+ }
+
+ /*
+ * general case
+ */
+ for( i = A->n, y = 0; i > 0; i-- )
+ {
+ x = A->p[i - 1];
+ y = ( y << biH ) | ( x >> biH );
+ z = y / b;
+ y -= z * b;
+
+ x <<= biH;
+ y = ( y << biH ) | ( x >> biH );
+ z = y / b;
+ y -= z * b;
+ }
+
+ /*
+ * If A is negative, then the current y represents a negative value.
+ * Flipping it to the positive side.
+ */
+ if( A->s < 0 && y != 0 )
+ y = b - y;
+
+ *r = y;
+
+ return( 0 );
+}
+
+/*
+ * Fast Montgomery initialization (thanks to Tom St Denis)
+ */
+static void mpi_montg_init( t_uint *mm, const mpi *N )
+{
+ t_uint x, m0 = N->p[0];
+
+ x = m0;
+ x += ( ( m0 + 2 ) & 4 ) << 1;
+ x *= ( 2 - ( m0 * x ) );
+
+ if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
+ if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
+ if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
+
+ *mm = ~x + 1;
+}
+
+/*
+ * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
+ */
+static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
+{
+ size_t i, n, m;
+ t_uint u0, u1, *d;
+
+ memset( T->p, 0, T->n * ciL );
+
+ d = T->p;
+ n = N->n;
+ m = ( B->n < n ) ? B->n : n;
+
+ for( i = 0; i < n; i++ )
+ {
+ /*
+ * T = (T + u0*B + u1*N) / 2^biL
+ */
+ u0 = A->p[i];
+ u1 = ( d[0] + u0 * B->p[0] ) * mm;
+
+ mpi_mul_hlp( m, B->p, d, u0 );
+ mpi_mul_hlp( n, N->p, d, u1 );
+
+ *d++ = u0; d[n + 1] = 0;
+ }
+
+ memcpy( A->p, d, (n + 1) * ciL );
+
+ if( mpi_cmp_abs( A, N ) >= 0 )
+ mpi_sub_hlp( n, N->p, A->p );
+ else
+ /* prevent timing attacks */
+ mpi_sub_hlp( n, A->p, T->p );
+}
+
+/*
+ * Montgomery reduction: A = A * R^-1 mod N
+ */
+static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
+{
+ t_uint z = 1;
+ mpi U;
+
+ U.n = U.s = (int) z;
+ U.p = &z;
+
+ mpi_montmul( A, &U, N, mm, T );
+}
+
+/*
+ * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
+ */
+int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
+{
+ int ret;
+ size_t wbits, wsize, one = 1;
+ size_t i, j, nblimbs;
+ size_t bufsize, nbits;
+ t_uint ei, mm, state;
+ mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
+ int neg;
+
+ if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ if( mpi_cmp_int( E, 0 ) < 0 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ /*
+ * Init temps and window size
+ */
+ mpi_montg_init( &mm, N );
+ mpi_init( &RR ); mpi_init( &T );
+ memset( W, 0, sizeof( W ) );
+
+ i = mpi_msb( E );
+
+ wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
+ ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
+
+ if( wsize > POLARSSL_MPI_WINDOW_SIZE )
+ wsize = POLARSSL_MPI_WINDOW_SIZE;
+
+ j = N->n + 1;
+ MPI_CHK( mpi_grow( X, j ) );
+ MPI_CHK( mpi_grow( &W[1], j ) );
+ MPI_CHK( mpi_grow( &T, j * 2 ) );
+
+ /*
+ * Compensate for negative A (and correct at the end)
+ */
+ neg = ( A->s == -1 );
+
+ mpi_init( &Apos );
+ if( neg )
+ {
+ MPI_CHK( mpi_copy( &Apos, A ) );
+ Apos.s = 1;
+ A = &Apos;
+ }
+
+ /*
+ * If 1st call, pre-compute R^2 mod N
+ */
+ if( _RR == NULL || _RR->p == NULL )
+ {
+ MPI_CHK( mpi_lset( &RR, 1 ) );
+ MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
+ MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
+
+ if( _RR != NULL )
+ memcpy( _RR, &RR, sizeof( mpi ) );
+ }
+ else
+ memcpy( &RR, _RR, sizeof( mpi ) );
+
+ /*
+ * W[1] = A * R^2 * R^-1 mod N = A * R mod N
+ */
+ if( mpi_cmp_mpi( A, N ) >= 0 )
+ mpi_mod_mpi( &W[1], A, N );
+ else mpi_copy( &W[1], A );
+
+ mpi_montmul( &W[1], &RR, N, mm, &T );
+
+ /*
+ * X = R^2 * R^-1 mod N = R mod N
+ */
+ MPI_CHK( mpi_copy( X, &RR ) );
+ mpi_montred( X, N, mm, &T );
+
+ if( wsize > 1 )
+ {
+ /*
+ * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
+ */
+ j = one << (wsize - 1);
+
+ MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
+ MPI_CHK( mpi_copy( &W[j], &W[1] ) );
+
+ for( i = 0; i < wsize - 1; i++ )
+ mpi_montmul( &W[j], &W[j], N, mm, &T );
+
+ /*
+ * W[i] = W[i - 1] * W[1]
+ */
+ for( i = j + 1; i < (one << wsize); i++ )
+ {
+ MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
+ MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
+
+ mpi_montmul( &W[i], &W[1], N, mm, &T );
+ }
+ }
+
+ nblimbs = E->n;
+ bufsize = 0;
+ nbits = 0;
+ wbits = 0;
+ state = 0;
+
+ while( 1 )
+ {
+ if( bufsize == 0 )
+ {
+ if( nblimbs-- == 0 )
+ break;
+
+ bufsize = sizeof( t_uint ) << 3;
+ }
+
+ bufsize--;
+
+ ei = (E->p[nblimbs] >> bufsize) & 1;
+
+ /*
+ * skip leading 0s
+ */
+ if( ei == 0 && state == 0 )
+ continue;
+
+ if( ei == 0 && state == 1 )
+ {
+ /*
+ * out of window, square X
+ */
+ mpi_montmul( X, X, N, mm, &T );
+ continue;
+ }
+
+ /*
+ * add ei to current window
+ */
+ state = 2;
+
+ nbits++;
+ wbits |= (ei << (wsize - nbits));
+
+ if( nbits == wsize )
+ {
+ /*
+ * X = X^wsize R^-1 mod N
+ */
+ for( i = 0; i < wsize; i++ )
+ mpi_montmul( X, X, N, mm, &T );
+
+ /*
+ * X = X * W[wbits] R^-1 mod N
+ */
+ mpi_montmul( X, &W[wbits], N, mm, &T );
+
+ state--;
+ nbits = 0;
+ wbits = 0;
+ }
+ }
+
+ /*
+ * process the remaining bits
+ */
+ for( i = 0; i < nbits; i++ )
+ {
+ mpi_montmul( X, X, N, mm, &T );
+
+ wbits <<= 1;
+
+ if( (wbits & (one << wsize)) != 0 )
+ mpi_montmul( X, &W[1], N, mm, &T );
+ }
+
+ /*
+ * X = A^E * R * R^-1 mod N = A^E mod N
+ */
+ mpi_montred( X, N, mm, &T );
+
+ if( neg )
+ {
+ X->s = -1;
+ mpi_add_mpi( X, N, X );
+ }
+
+cleanup:
+
+ for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
+ mpi_free( &W[i] );
+
+ mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
+
+ if( _RR == NULL )
+ mpi_free( &RR );
+
+ return( ret );
+}
+
+/*
+ * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
+ */
+int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t lz, lzt;
+ mpi TG, TA, TB;
+
+ mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
+
+ MPI_CHK( mpi_copy( &TA, A ) );
+ MPI_CHK( mpi_copy( &TB, B ) );
+
+ lz = mpi_lsb( &TA );
+ lzt = mpi_lsb( &TB );
+
+ if ( lzt < lz )
+ lz = lzt;
+
+ MPI_CHK( mpi_shift_r( &TA, lz ) );
+ MPI_CHK( mpi_shift_r( &TB, lz ) );
+
+ TA.s = TB.s = 1;
+
+ while( mpi_cmp_int( &TA, 0 ) != 0 )
+ {
+ MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
+ MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
+
+ if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
+ MPI_CHK( mpi_shift_r( &TA, 1 ) );
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
+ MPI_CHK( mpi_shift_r( &TB, 1 ) );
+ }
+ }
+
+ MPI_CHK( mpi_shift_l( &TB, lz ) );
+ MPI_CHK( mpi_copy( G, &TB ) );
+
+cleanup:
+
+ mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
+
+ return( ret );
+}
+
+int mpi_fill_random( mpi *X, size_t size,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+
+ MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) );
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
+ */
+int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
+{
+ int ret;
+ mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
+
+ if( mpi_cmp_int( N, 0 ) <= 0 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
+ mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
+ mpi_init( &V1 ); mpi_init( &V2 );
+
+ MPI_CHK( mpi_gcd( &G, A, N ) );
+
+ if( mpi_cmp_int( &G, 1 ) != 0 )
+ {
+ ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+ goto cleanup;
+ }
+
+ MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
+ MPI_CHK( mpi_copy( &TU, &TA ) );
+ MPI_CHK( mpi_copy( &TB, N ) );
+ MPI_CHK( mpi_copy( &TV, N ) );
+
+ MPI_CHK( mpi_lset( &U1, 1 ) );
+ MPI_CHK( mpi_lset( &U2, 0 ) );
+ MPI_CHK( mpi_lset( &V1, 0 ) );
+ MPI_CHK( mpi_lset( &V2, 1 ) );
+
+ do
+ {
+ while( ( TU.p[0] & 1 ) == 0 )
+ {
+ MPI_CHK( mpi_shift_r( &TU, 1 ) );
+
+ if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
+ {
+ MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
+ MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
+ }
+
+ MPI_CHK( mpi_shift_r( &U1, 1 ) );
+ MPI_CHK( mpi_shift_r( &U2, 1 ) );
+ }
+
+ while( ( TV.p[0] & 1 ) == 0 )
+ {
+ MPI_CHK( mpi_shift_r( &TV, 1 ) );
+
+ if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
+ {
+ MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
+ MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
+ }
+
+ MPI_CHK( mpi_shift_r( &V1, 1 ) );
+ MPI_CHK( mpi_shift_r( &V2, 1 ) );
+ }
+
+ if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
+ MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
+ MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
+ MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
+ MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
+ }
+ }
+ while( mpi_cmp_int( &TU, 0 ) != 0 );
+
+ while( mpi_cmp_int( &V1, 0 ) < 0 )
+ MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
+
+ while( mpi_cmp_mpi( &V1, N ) >= 0 )
+ MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
+
+ MPI_CHK( mpi_copy( X, &V1 ) );
+
+cleanup:
+
+ mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
+ mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
+ mpi_free( &V1 ); mpi_free( &V2 );
+
+ return( ret );
+}
+
+#if defined(POLARSSL_GENPRIME)
+
+static const int small_prime[] =
+{
+ 3, 5, 7, 11, 13, 17, 19, 23,
+ 29, 31, 37, 41, 43, 47, 53, 59,
+ 61, 67, 71, 73, 79, 83, 89, 97,
+ 101, 103, 107, 109, 113, 127, 131, 137,
+ 139, 149, 151, 157, 163, 167, 173, 179,
+ 181, 191, 193, 197, 199, 211, 223, 227,
+ 229, 233, 239, 241, 251, 257, 263, 269,
+ 271, 277, 281, 283, 293, 307, 311, 313,
+ 317, 331, 337, 347, 349, 353, 359, 367,
+ 373, 379, 383, 389, 397, 401, 409, 419,
+ 421, 431, 433, 439, 443, 449, 457, 461,
+ 463, 467, 479, 487, 491, 499, 503, 509,
+ 521, 523, 541, 547, 557, 563, 569, 571,
+ 577, 587, 593, 599, 601, 607, 613, 617,
+ 619, 631, 641, 643, 647, 653, 659, 661,
+ 673, 677, 683, 691, 701, 709, 719, 727,
+ 733, 739, 743, 751, 757, 761, 769, 773,
+ 787, 797, 809, 811, 821, 823, 827, 829,
+ 839, 853, 857, 859, 863, 877, 881, 883,
+ 887, 907, 911, 919, 929, 937, 941, 947,
+ 953, 967, 971, 977, 983, 991, 997, -103
+};
+
+/*
+ * Miller-Rabin primality test (HAC 4.24)
+ */
+int mpi_is_prime( mpi *X,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret, xs;
+ size_t i, j, n, s;
+ mpi W, R, T, A, RR;
+
+ if( mpi_cmp_int( X, 0 ) == 0 ||
+ mpi_cmp_int( X, 1 ) == 0 )
+ return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+
+ if( mpi_cmp_int( X, 2 ) == 0 )
+ return( 0 );
+
+ mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
+ mpi_init( &RR );
+
+ xs = X->s; X->s = 1;
+
+ /*
+ * test trivial factors first
+ */
+ if( ( X->p[0] & 1 ) == 0 )
+ return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+
+ for( i = 0; small_prime[i] > 0; i++ )
+ {
+ t_uint r;
+
+ if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
+ return( 0 );
+
+ MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
+
+ if( r == 0 )
+ return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+ }
+
+ /*
+ * W = |X| - 1
+ * R = W >> lsb( W )
+ */
+ MPI_CHK( mpi_sub_int( &W, X, 1 ) );
+ s = mpi_lsb( &W );
+ MPI_CHK( mpi_copy( &R, &W ) );
+ MPI_CHK( mpi_shift_r( &R, s ) );
+
+ i = mpi_msb( X );
+ /*
+ * HAC, table 4.4
+ */
+ n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
+ ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
+ ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
+
+ for( i = 0; i < n; i++ )
+ {
+ /*
+ * pick a random A, 1 < A < |X| - 1
+ */
+ MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
+
+ if( mpi_cmp_mpi( &A, &W ) >= 0 )
+ {
+ j = mpi_msb( &A ) - mpi_msb( &W );
+ MPI_CHK( mpi_shift_r( &A, j + 1 ) );
+ }
+ A.p[0] |= 3;
+
+ /*
+ * A = A^R mod |X|
+ */
+ MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
+
+ if( mpi_cmp_mpi( &A, &W ) == 0 ||
+ mpi_cmp_int( &A, 1 ) == 0 )
+ continue;
+
+ j = 1;
+ while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
+ {
+ /*
+ * A = A * A mod |X|
+ */
+ MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
+ MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
+
+ if( mpi_cmp_int( &A, 1 ) == 0 )
+ break;
+
+ j++;
+ }
+
+ /*
+ * not prime if A != |X| - 1 or A == 1
+ */
+ if( mpi_cmp_mpi( &A, &W ) != 0 ||
+ mpi_cmp_int( &A, 1 ) == 0 )
+ {
+ ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+ break;
+ }
+ }
+
+cleanup:
+
+ X->s = xs;
+
+ mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
+ mpi_free( &RR );
+
+ return( ret );
+}
+
+/*
+ * Prime number generation
+ */
+int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+ size_t k, n;
+ mpi Y;
+
+ if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ mpi_init( &Y );
+
+ n = BITS_TO_LIMBS( nbits );
+
+ MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
+
+ k = mpi_msb( X );
+ if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
+ if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
+
+ X->p[0] |= 3;
+
+ if( dh_flag == 0 )
+ {
+ while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
+ {
+ if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+ goto cleanup;
+
+ MPI_CHK( mpi_add_int( X, X, 2 ) );
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
+ MPI_CHK( mpi_shift_r( &Y, 1 ) );
+
+ while( 1 )
+ {
+ if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
+ {
+ if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
+ break;
+
+ if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+ goto cleanup;
+ }
+
+ if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+ goto cleanup;
+
+ MPI_CHK( mpi_add_int( &Y, X, 1 ) );
+ MPI_CHK( mpi_add_int( X, X, 2 ) );
+ MPI_CHK( mpi_shift_r( &Y, 1 ) );
+ }
+ }
+
+cleanup:
+
+ mpi_free( &Y );
+
+ return( ret );
+}
+
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+
+#define GCD_PAIR_COUNT 3
+
+static const int gcd_pairs[GCD_PAIR_COUNT][3] =
+{
+ { 693, 609, 21 },
+ { 1764, 868, 28 },
+ { 768454923, 542167814, 1 }
+};
+
+/*
+ * Checkup routine
+ */
+int mpi_self_test( int verbose )
+{
+ int ret, i;
+ mpi A, E, N, X, Y, U, V;
+
+ mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
+ mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
+
+ MPI_CHK( mpi_read_string( &A, 16,
+ "EFE021C2645FD1DC586E69184AF4A31E" \
+ "D5F53E93B5F123FA41680867BA110131" \
+ "944FE7952E2517337780CB0DB80E61AA" \
+ "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
+
+ MPI_CHK( mpi_read_string( &E, 16,
+ "B2E7EFD37075B9F03FF989C7C5051C20" \
+ "34D2A323810251127E7BF8625A4F49A5" \
+ "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
+ "5B5C25763222FEFCCFC38B832366C29E" ) );
+
+ MPI_CHK( mpi_read_string( &N, 16,
+ "0066A198186C18C10B2F5ED9B522752A" \
+ "9830B69916E535C8F047518A889A43A5" \
+ "94B6BED27A168D31D4A52F88925AA8F5" ) );
+
+ MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "602AB7ECA597A3D6B56FF9829A5E8B85" \
+ "9E857EA95A03512E2BAE7391688D264A" \
+ "A5663B0341DB9CCFD2C4C5F421FEC814" \
+ "8001B72E848A38CAE1C65F78E56ABDEF" \
+ "E12D3C039B8A02D6BE593F0BBBDA56F1" \
+ "ECF677152EF804370C1A305CAF3B5BF1" \
+ "30879B56C61DE584A0F53A2447A51E" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #1 (mul_mpi): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "256567336059E52CAE22925474705F39A94" ) );
+
+ MPI_CHK( mpi_read_string( &V, 16,
+ "6613F26162223DF488E9CD48CC132C7A" \
+ "0AC93C701B001B092E4E5B9F73BCD27B" \
+ "9EE50D0657C77F374E903CDFA4C642" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #2 (div_mpi): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 ||
+ mpi_cmp_mpi( &Y, &V ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "36E139AEA55215609D2816998ED020BB" \
+ "BD96C37890F65171D948E9BC7CBAA4D9" \
+ "325D24D6A3C12710F10A09FA08AB87" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #3 (exp_mod): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+#if defined(POLARSSL_GENPRIME)
+ MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
+ "C3DBA76456363A10869622EAC2DD84EC" \
+ "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #4 (inv_mod): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+#endif
+
+ if( verbose != 0 )
+ printf( " MPI test #5 (simple gcd): " );
+
+ for ( i = 0; i < GCD_PAIR_COUNT; i++)
+ {
+ MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
+ MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
+
+ MPI_CHK( mpi_gcd( &A, &X, &Y ) );
+
+ if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed at %d\n", i );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+cleanup:
+
+ if( ret != 0 && verbose != 0 )
+ printf( "Unexpected error, return code = %08X\n", ret );
+
+ mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
+ mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( ret );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/bignum.h b/polarssl/bignum.h
new file mode 100644
index 0000000..ad06b57
--- /dev/null
+++ b/polarssl/bignum.h
@@ -0,0 +1,685 @@
+/**
+ * \file bignum.h
+ *
+ * \brief Multi-precision integer library
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_BIGNUM_H
+#define POLARSSL_BIGNUM_H
+
+#include
+#include
+
+#include "polarssl/config.h"
+
+#ifdef _MSC_VER
+#include
+#if (_MSC_VER <= 1200)
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+#else
+typedef INT16 int16_t;
+typedef UINT16 uint16_t;
+#endif
+typedef INT32 int32_t;
+typedef INT64 int64_t;
+typedef UINT32 uint32_t;
+typedef UINT64 uint64_t;
+#else
+#include
+#endif
+
+#define POLARSSL_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */
+#define POLARSSL_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */
+#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */
+#define POLARSSL_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */
+#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */
+#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */
+#define POLARSSL_ERR_MPI_MALLOC_FAILED -0x0010 /**< Memory allocation failed. */
+
+#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup
+
+/*
+ * Maximum size MPIs are allowed to grow to in number of limbs.
+ */
+#define POLARSSL_MPI_MAX_LIMBS 10000
+
+#if !defined(POLARSSL_CONFIG_OPTIONS)
+/*
+ * Maximum window size used for modular exponentiation. Default: 6
+ * Minimum value: 1. Maximum value: 6.
+ *
+ * Result is an array of ( 2 << POLARSSL_MPI_WINDOW_SIZE ) MPIs used
+ * for the sliding window calculation. (So 64 by default)
+ *
+ * Reduction in size, reduces speed.
+ */
+#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */
+
+/*
+ * Maximum size of MPIs allowed in bits and bytes for user-MPIs.
+ * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits )
+ *
+ * Note: Calculations can results temporarily in larger MPIs. So the number
+ * of limbs required (POLARSSL_MPI_MAX_LIMBS) is higher.
+ */
+#define POLARSSL_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */
+
+#endif /* !POLARSSL_CONFIG_OPTIONS */
+
+#define POLARSSL_MPI_MAX_BITS ( 8 * POLARSSL_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */
+
+/*
+ * When reading from files with mpi_read_file() and writing to files with
+ * mpi_write_file() the buffer should have space
+ * for a (short) label, the MPI (in the provided radix), the newline
+ * characters and the '\0'.
+ *
+ * By default we assume at least a 10 char label, a minimum radix of 10
+ * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars).
+ * Autosized at compile time for at least a 10 char label, a minimum radix
+ * of 10 (decimal) for a number of POLARSSL_MPI_MAX_BITS size.
+ *
+ * This used to be statically sized to 1250 for a maximum of 4096 bit
+ * numbers (1234 decimal chars).
+ *
+ * Calculate using the formula:
+ * POLARSSL_MPI_RW_BUFFER_SIZE = ceil(POLARSSL_MPI_MAX_BITS / ln(10) * ln(2)) +
+ * LabelSize + 6
+ */
+#define POLARSSL_MPI_MAX_BITS_SCALE100 ( 100 * POLARSSL_MPI_MAX_BITS )
+#define LN_2_DIV_LN_10_SCALE100 332
+#define POLARSSL_MPI_RW_BUFFER_SIZE ( ((POLARSSL_MPI_MAX_BITS_SCALE100 + LN_2_DIV_LN_10_SCALE100 - 1) / LN_2_DIV_LN_10_SCALE100) + 10 + 6 )
+
+/*
+ * Define the base integer type, architecture-wise
+ */
+#if defined(POLARSSL_HAVE_INT8)
+typedef signed char t_sint;
+typedef unsigned char t_uint;
+typedef uint16_t t_udbl;
+#define POLARSSL_HAVE_UDBL
+#else
+#if defined(POLARSSL_HAVE_INT16)
+typedef int16_t t_sint;
+typedef uint16_t t_uint;
+typedef uint32_t t_udbl;
+#define POLARSSL_HAVE_UDBL
+#else
+ #if ( defined(_MSC_VER) && defined(_M_AMD64) )
+ typedef int64_t t_sint;
+ typedef uint64_t t_uint;
+ #else
+ #if ( defined(__GNUC__) && ( \
+ defined(__amd64__) || defined(__x86_64__) || \
+ defined(__ppc64__) || defined(__powerpc64__) || \
+ defined(__ia64__) || defined(__alpha__) || \
+ (defined(__sparc__) && defined(__arch64__)) || \
+ defined(__s390x__) ) )
+ typedef int64_t t_sint;
+ typedef uint64_t t_uint;
+ typedef unsigned int t_udbl __attribute__((mode(TI)));
+ #define POLARSSL_HAVE_UDBL
+ #else
+ typedef int32_t t_sint;
+ typedef uint32_t t_uint;
+ #if ( defined(_MSC_VER) && defined(_M_IX86) )
+ typedef uint64_t t_udbl;
+ #define POLARSSL_HAVE_UDBL
+ #else
+ #if defined( POLARSSL_HAVE_LONGLONG )
+ typedef unsigned long long t_udbl;
+ #define POLARSSL_HAVE_UDBL
+ #endif
+ #endif
+ #endif
+ #endif
+#endif /* POLARSSL_HAVE_INT16 */
+#endif /* POLARSSL_HAVE_INT8 */
+
+/**
+ * \brief MPI structure
+ */
+typedef struct
+{
+ int s; /*!< integer sign */
+ size_t n; /*!< total # of limbs */
+ t_uint *p; /*!< pointer to limbs */
+}
+mpi;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Initialize one MPI
+ *
+ * \param X One MPI to initialize.
+ */
+void mpi_init( mpi *X );
+
+/**
+ * \brief Unallocate one MPI
+ *
+ * \param X One MPI to unallocate.
+ */
+void mpi_free( mpi *X );
+
+/**
+ * \brief Enlarge to the specified number of limbs
+ *
+ * \param X MPI to grow
+ * \param nblimbs The target number of limbs
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_grow( mpi *X, size_t nblimbs );
+
+/**
+ * \brief Copy the contents of Y into X
+ *
+ * \param X Destination MPI
+ * \param Y Source MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_copy( mpi *X, const mpi *Y );
+
+/**
+ * \brief Swap the contents of X and Y
+ *
+ * \param X First MPI value
+ * \param Y Second MPI value
+ */
+void mpi_swap( mpi *X, mpi *Y );
+
+/**
+ * \brief Set value from integer
+ *
+ * \param X MPI to set
+ * \param z Value to use
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_lset( mpi *X, t_sint z );
+
+/**
+ * \brief Get a specific bit from X
+ *
+ * \param X MPI to use
+ * \param pos Zero-based index of the bit in X
+ *
+ * \return Either a 0 or a 1
+ */
+int mpi_get_bit( const mpi *X, size_t pos );
+
+/**
+ * \brief Set a bit of X to a specific value of 0 or 1
+ *
+ * \note Will grow X if necessary to set a bit to 1 in a not yet
+ * existing limb. Will not grow if bit should be set to 0
+ *
+ * \param X MPI to use
+ * \param pos Zero-based index of the bit in X
+ * \param val The value to set the bit to (0 or 1)
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1
+ */
+int mpi_set_bit( mpi *X, size_t pos, unsigned char val );
+
+/**
+ * \brief Return the number of zero-bits before the least significant
+ * '1' bit
+ *
+ * Note: Thus also the zero-based index of the least significant '1' bit
+ *
+ * \param X MPI to use
+ */
+size_t mpi_lsb( const mpi *X );
+
+/**
+ * \brief Return the number of bits up to and including the most
+ * significant '1' bit'
+ *
+ * Note: Thus also the one-based index of the most significant '1' bit
+ *
+ * \param X MPI to use
+ */
+size_t mpi_msb( const mpi *X );
+
+/**
+ * \brief Return the total size in bytes
+ *
+ * \param X MPI to use
+ */
+size_t mpi_size( const mpi *X );
+
+/**
+ * \brief Import from an ASCII string
+ *
+ * \param X Destination MPI
+ * \param radix Input numeric base
+ * \param s Null-terminated string buffer
+ *
+ * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code
+ */
+int mpi_read_string( mpi *X, int radix, const char *s );
+
+/**
+ * \brief Export into an ASCII string
+ *
+ * \param X Source MPI
+ * \param radix Output numeric base
+ * \param s String buffer
+ * \param slen String buffer size
+ *
+ * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code.
+ * *slen is always updated to reflect the amount
+ * of data that has (or would have) been written.
+ *
+ * \note Call this function with *slen = 0 to obtain the
+ * minimum required buffer size in *slen.
+ */
+int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief Read X from an opened file
+ *
+ * \param X Destination MPI
+ * \param radix Input numeric base
+ * \param fin Input file handle
+ *
+ * \return 0 if successful, POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if
+ * the file read buffer is too small or a
+ * POLARSSL_ERR_MPI_XXX error code
+ */
+int mpi_read_file( mpi *X, int radix, FILE *fin );
+
+/**
+ * \brief Write X into an opened file, or stdout if fout is NULL
+ *
+ * \param p Prefix, can be NULL
+ * \param X Source MPI
+ * \param radix Output numeric base
+ * \param fout Output file handle (can be NULL)
+ *
+ * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code
+ *
+ * \note Set fout == NULL to print X on the console.
+ */
+int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout );
+#endif /* POLARSSL_FS_IO */
+
+/**
+ * \brief Import X from unsigned binary data, big endian
+ *
+ * \param X Destination MPI
+ * \param buf Input buffer
+ * \param buflen Input buffer size
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen );
+
+/**
+ * \brief Export X into unsigned binary data, big endian
+ *
+ * \param X Source MPI
+ * \param buf Output buffer
+ * \param buflen Output buffer size
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
+ */
+int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen );
+
+/**
+ * \brief Left-shift: X <<= count
+ *
+ * \param X MPI to shift
+ * \param count Amount to shift
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_shift_l( mpi *X, size_t count );
+
+/**
+ * \brief Right-shift: X >>= count
+ *
+ * \param X MPI to shift
+ * \param count Amount to shift
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_shift_r( mpi *X, size_t count );
+
+/**
+ * \brief Compare unsigned values
+ *
+ * \param X Left-hand MPI
+ * \param Y Right-hand MPI
+ *
+ * \return 1 if |X| is greater than |Y|,
+ * -1 if |X| is lesser than |Y| or
+ * 0 if |X| is equal to |Y|
+ */
+int mpi_cmp_abs( const mpi *X, const mpi *Y );
+
+/**
+ * \brief Compare signed values
+ *
+ * \param X Left-hand MPI
+ * \param Y Right-hand MPI
+ *
+ * \return 1 if X is greater than Y,
+ * -1 if X is lesser than Y or
+ * 0 if X is equal to Y
+ */
+int mpi_cmp_mpi( const mpi *X, const mpi *Y );
+
+/**
+ * \brief Compare signed values
+ *
+ * \param X Left-hand MPI
+ * \param z The integer value to compare to
+ *
+ * \return 1 if X is greater than z,
+ * -1 if X is lesser than z or
+ * 0 if X is equal to z
+ */
+int mpi_cmp_int( const mpi *X, t_sint z );
+
+/**
+ * \brief Unsigned addition: X = |A| + |B|
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_add_abs( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Unsigned substraction: X = |A| - |B|
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A
+ */
+int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Signed addition: X = A + B
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Signed substraction: X = A - B
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Signed addition: X = A + b
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param b The integer value to add
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_add_int( mpi *X, const mpi *A, t_sint b );
+
+/**
+ * \brief Signed substraction: X = A - b
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param b The integer value to subtract
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_sub_int( mpi *X, const mpi *A, t_sint b );
+
+/**
+ * \brief Baseline multiplication: X = A * B
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Baseline multiplication: X = A * b
+ * Note: b is an unsigned integer type, thus
+ * Negative values of b are ignored.
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param b The integer value to multiply with
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_mul_int( mpi *X, const mpi *A, t_sint b );
+
+/**
+ * \brief Division by mpi: A = Q * B + R
+ *
+ * \param Q Destination MPI for the quotient
+ * \param R Destination MPI for the rest value
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0
+ *
+ * \note Either Q or R can be NULL.
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B );
+
+/**
+ * \brief Division by int: A = Q * b + R
+ *
+ * \param Q Destination MPI for the quotient
+ * \param R Destination MPI for the rest value
+ * \param A Left-hand MPI
+ * \param b Integer to divide by
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ *
+ * \note Either Q or R can be NULL.
+ */
+int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b );
+
+/**
+ * \brief Modulo: R = A mod B
+ *
+ * \param R Destination MPI for the rest value
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0,
+ * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0
+ */
+int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B );
+
+/**
+ * \brief Modulo: r = A mod b
+ *
+ * \param r Destination t_uint
+ * \param A Left-hand MPI
+ * \param b Integer to divide by
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0,
+ * POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0
+ */
+int mpi_mod_int( t_uint *r, const mpi *A, t_sint b );
+
+/**
+ * \brief Sliding-window exponentiation: X = A^E mod N
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param E Exponent MPI
+ * \param N Modular MPI
+ * \param _RR Speed-up MPI used for recalculations
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even or if
+ * E is negative
+ *
+ * \note _RR is used to avoid re-computing R*R mod N across
+ * multiple calls, which speeds up things a bit. It can
+ * be set to NULL if the extra performance is unneeded.
+ */
+int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR );
+
+/**
+ * \brief Fill an MPI X with size bytes of random
+ *
+ * \param X Destination MPI
+ * \param size Size in bytes
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_fill_random( mpi *X, size_t size,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Greatest common divisor: G = gcd(A, B)
+ *
+ * \param G Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_gcd( mpi *G, const mpi *A, const mpi *B );
+
+/**
+ * \brief Modular inverse: X = A^-1 mod N
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param N Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil
+ POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N
+ */
+int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N );
+
+/**
+ * \brief Miller-Rabin primality test
+ *
+ * \param X MPI to check
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful (probably prime),
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime
+ */
+int mpi_is_prime( mpi *X,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Prime number generation
+ *
+ * \param X Destination MPI
+ * \param nbits Required size of X in bits ( 3 <= nbits <= POLARSSL_MPI_MAX_BITS )
+ * \param dh_flag If 1, then (X-1)/2 will be prime too
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful (probably prime),
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
+ */
+int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mpi_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* bignum.h */
diff --git a/polarssl/blowfish.c b/polarssl/blowfish.c
new file mode 100644
index 0000000..719aea6
--- /dev/null
+++ b/polarssl/blowfish.c
@@ -0,0 +1,632 @@
+/*
+ * Blowfish implementation
+ *
+ * Copyright (C) 2012-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The Blowfish block cipher was designed by Bruce Schneier in 1993.
+ * http://www.schneier.com/blowfish.html
+ * http://en.wikipedia.org/wiki/Blowfish_%28cipher%29
+ *
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_BLOWFISH_C)
+
+#include "polarssl/blowfish.h"
+
+#if !defined(POLARSSL_BLOWFISH_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+static const uint32_t P[BLOWFISH_ROUNDS + 2] = {
+ 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L,
+ 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L,
+ 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL,
+ 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L,
+ 0x9216D5D9L, 0x8979FB1BL
+};
+
+/* declarations of data at the end of this file */
+static const uint32_t S[4][256];
+
+static uint32_t F(blowfish_context *ctx, uint32_t x)
+{
+ unsigned short a, b, c, d;
+ uint32_t y;
+
+ d = (unsigned short)(x & 0xFF);
+ x >>= 8;
+ c = (unsigned short)(x & 0xFF);
+ x >>= 8;
+ b = (unsigned short)(x & 0xFF);
+ x >>= 8;
+ a = (unsigned short)(x & 0xFF);
+ y = ctx->S[0][a] + ctx->S[1][b];
+ y = y ^ ctx->S[2][c];
+ y = y + ctx->S[3][d];
+
+ return y;
+}
+
+static void blowfish_enc(blowfish_context *ctx, uint32_t *xl, uint32_t *xr)
+{
+ uint32_t Xl, Xr, temp;
+ short i;
+
+ Xl = *xl;
+ Xr = *xr;
+
+ for (i = 0; i < BLOWFISH_ROUNDS; ++i)
+ {
+ Xl = Xl ^ ctx->P[i];
+ Xr = F(ctx, Xl) ^ Xr;
+
+ temp = Xl;
+ Xl = Xr;
+ Xr = temp;
+ }
+
+ temp = Xl;
+ Xl = Xr;
+ Xr = temp;
+
+ Xr = Xr ^ ctx->P[BLOWFISH_ROUNDS];
+ Xl = Xl ^ ctx->P[BLOWFISH_ROUNDS + 1];
+
+ *xl = Xl;
+ *xr = Xr;
+}
+
+static void blowfish_dec(blowfish_context *ctx, uint32_t *xl, uint32_t *xr)
+{
+ uint32_t Xl, Xr, temp;
+ short i;
+
+ Xl = *xl;
+ Xr = *xr;
+
+ for (i = BLOWFISH_ROUNDS + 1; i > 1; --i)
+ {
+ Xl = Xl ^ ctx->P[i];
+ Xr = F(ctx, Xl) ^ Xr;
+
+ temp = Xl;
+ Xl = Xr;
+ Xr = temp;
+ }
+
+ temp = Xl;
+ Xl = Xr;
+ Xr = temp;
+
+ Xr = Xr ^ ctx->P[1];
+ Xl = Xl ^ ctx->P[0];
+
+ *xl = Xl;
+ *xr = Xr;
+}
+
+/*
+ * Blowfish key schedule
+ */
+int blowfish_setkey( blowfish_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+ unsigned int i, j, k;
+ uint32_t data, datal, datar;
+
+ if( keysize < BLOWFISH_MIN_KEY || keysize > BLOWFISH_MAX_KEY ||
+ ( keysize % 8 ) )
+ {
+ return POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH;
+ }
+
+ keysize >>= 3;
+
+ for( i = 0; i < 4; i++ )
+ {
+ for( j = 0; j < 256; j++ )
+ ctx->S[i][j] = S[i][j];
+ }
+
+ j = 0;
+ for( i = 0; i < BLOWFISH_ROUNDS + 2; ++i )
+ {
+ data = 0x00000000;
+ for( k = 0; k < 4; ++k )
+ {
+ data = ( data << 8 ) | key[j++];
+ if( j >= keysize )
+ j = 0;
+ }
+ ctx->P[i] = P[i] ^ data;
+ }
+
+ datal = 0x00000000;
+ datar = 0x00000000;
+
+ for( i = 0; i < BLOWFISH_ROUNDS + 2; i += 2 )
+ {
+ blowfish_enc( ctx, &datal, &datar );
+ ctx->P[i] = datal;
+ ctx->P[i + 1] = datar;
+ }
+
+ for( i = 0; i < 4; i++ )
+ {
+ for( j = 0; j < 256; j += 2 )
+ {
+ blowfish_enc( ctx, &datal, &datar );
+ ctx->S[i][j] = datal;
+ ctx->S[i][j + 1] = datar;
+ }
+ }
+ return( 0 );
+}
+
+/*
+ * Blowfish-ECB block encryption/decryption
+ */
+int blowfish_crypt_ecb( blowfish_context *ctx,
+ int mode,
+ const unsigned char input[BLOWFISH_BLOCKSIZE],
+ unsigned char output[BLOWFISH_BLOCKSIZE] )
+{
+ uint32_t X0, X1;
+
+ GET_UINT32_BE( X0, input, 0 );
+ GET_UINT32_BE( X1, input, 4 );
+
+ if( mode == BLOWFISH_DECRYPT )
+ {
+ blowfish_dec(ctx, &X0, &X1);
+ }
+ else /* BLOWFISH_ENCRYPT */
+ {
+ blowfish_enc(ctx, &X0, &X1);
+ }
+
+ PUT_UINT32_BE( X0, output, 0 );
+ PUT_UINT32_BE( X1, output, 4 );
+
+ return( 0 );
+}
+
+/*
+ * Blowfish-CBC buffer encryption/decryption
+ */
+int blowfish_crypt_cbc( blowfish_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[BLOWFISH_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[BLOWFISH_BLOCKSIZE];
+
+ if( length % BLOWFISH_BLOCKSIZE )
+ return( POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH );
+
+ if( mode == BLOWFISH_DECRYPT )
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, BLOWFISH_BLOCKSIZE );
+ blowfish_crypt_ecb( ctx, mode, input, output );
+
+ for( i = 0; i < BLOWFISH_BLOCKSIZE;i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, BLOWFISH_BLOCKSIZE );
+
+ input += BLOWFISH_BLOCKSIZE;
+ output += BLOWFISH_BLOCKSIZE;
+ length -= BLOWFISH_BLOCKSIZE;
+ }
+ }
+ else
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < BLOWFISH_BLOCKSIZE; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ blowfish_crypt_ecb( ctx, mode, output, output );
+ memcpy( iv, output, BLOWFISH_BLOCKSIZE );
+
+ input += BLOWFISH_BLOCKSIZE;
+ output += BLOWFISH_BLOCKSIZE;
+ length -= BLOWFISH_BLOCKSIZE;
+ }
+ }
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * Blowfish CFB buffer encryption/decryption
+ */
+int blowfish_crypt_cfb64( blowfish_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[BLOWFISH_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c;
+ size_t n = *iv_off;
+
+ if( mode == BLOWFISH_DECRYPT )
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ blowfish_crypt_ecb( ctx, BLOWFISH_ENCRYPT, iv, iv );
+
+ c = *input++;
+ *output++ = (unsigned char)( c ^ iv[n] );
+ iv[n] = (unsigned char) c;
+
+ n = (n + 1) % BLOWFISH_BLOCKSIZE;
+ }
+ }
+ else
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ blowfish_crypt_ecb( ctx, BLOWFISH_ENCRYPT, iv, iv );
+
+ iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+ n = (n + 1) % BLOWFISH_BLOCKSIZE;
+ }
+ }
+
+ *iv_off = n;
+
+ return( 0 );
+}
+#endif /*POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * Blowfish CTR buffer encryption/decryption
+ */
+int blowfish_crypt_ctr( blowfish_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[BLOWFISH_BLOCKSIZE],
+ unsigned char stream_block[BLOWFISH_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c, i;
+ size_t n = *nc_off;
+
+ while( length-- )
+ {
+ if( n == 0 ) {
+ blowfish_crypt_ecb( ctx, BLOWFISH_ENCRYPT, nonce_counter, stream_block );
+
+ for( i = BLOWFISH_BLOCKSIZE; i > 0; i-- )
+ if( ++nonce_counter[i - 1] != 0 )
+ break;
+ }
+ c = *input++;
+ *output++ = (unsigned char)( c ^ stream_block[n] );
+
+ n = (n + 1) % BLOWFISH_BLOCKSIZE;
+ }
+
+ *nc_off = n;
+
+ return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+static const uint32_t S[4][256] = {
+ { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,
+ 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L,
+ 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L,
+ 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL,
+ 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL,
+ 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L,
+ 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL,
+ 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL,
+ 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L,
+ 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L,
+ 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL,
+ 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL,
+ 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL,
+ 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L,
+ 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L,
+ 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L,
+ 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L,
+ 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L,
+ 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL,
+ 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L,
+ 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L,
+ 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L,
+ 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L,
+ 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL,
+ 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L,
+ 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL,
+ 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL,
+ 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L,
+ 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL,
+ 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L,
+ 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL,
+ 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L,
+ 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L,
+ 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL,
+ 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L,
+ 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L,
+ 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL,
+ 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L,
+ 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL,
+ 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L,
+ 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L,
+ 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL,
+ 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L,
+ 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L,
+ 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L,
+ 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L,
+ 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L,
+ 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL,
+ 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL,
+ 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L,
+ 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L,
+ 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L,
+ 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L,
+ 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL,
+ 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L,
+ 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL,
+ 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL,
+ 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L,
+ 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L,
+ 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L,
+ 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L,
+ 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L,
+ 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L,
+ 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL },
+ { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L,
+ 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L,
+ 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L,
+ 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL,
+ 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L,
+ 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L,
+ 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL,
+ 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L,
+ 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L,
+ 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L,
+ 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL,
+ 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL,
+ 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L,
+ 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L,
+ 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L,
+ 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L,
+ 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL,
+ 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL,
+ 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL,
+ 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L,
+ 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL,
+ 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L,
+ 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L,
+ 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL,
+ 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL,
+ 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L,
+ 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL,
+ 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L,
+ 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL,
+ 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL,
+ 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L,
+ 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L,
+ 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L,
+ 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L,
+ 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L,
+ 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L,
+ 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L,
+ 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL,
+ 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L,
+ 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL,
+ 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L,
+ 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L,
+ 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L,
+ 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L,
+ 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L,
+ 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L,
+ 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L,
+ 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L,
+ 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L,
+ 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L,
+ 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L,
+ 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L,
+ 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L,
+ 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L,
+ 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L,
+ 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L,
+ 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL,
+ 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL,
+ 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L,
+ 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL,
+ 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L,
+ 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L,
+ 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L,
+ 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L },
+ { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L,
+ 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L,
+ 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL,
+ 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L,
+ 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L,
+ 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L,
+ 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL,
+ 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL,
+ 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL,
+ 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L,
+ 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L,
+ 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL,
+ 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L,
+ 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL,
+ 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L,
+ 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL,
+ 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L,
+ 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL,
+ 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L,
+ 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL,
+ 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L,
+ 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L,
+ 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL,
+ 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L,
+ 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L,
+ 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L,
+ 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L,
+ 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL,
+ 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L,
+ 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL,
+ 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L,
+ 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL,
+ 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L,
+ 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL,
+ 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL,
+ 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL,
+ 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L,
+ 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L,
+ 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL,
+ 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL,
+ 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL,
+ 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL,
+ 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL,
+ 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L,
+ 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L,
+ 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L,
+ 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L,
+ 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL,
+ 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL,
+ 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L,
+ 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L,
+ 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L,
+ 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L,
+ 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L,
+ 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L,
+ 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L,
+ 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L,
+ 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L,
+ 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L,
+ 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL,
+ 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L,
+ 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL,
+ 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L,
+ 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L },
+ { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL,
+ 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL,
+ 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL,
+ 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L,
+ 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L,
+ 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L,
+ 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L,
+ 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L,
+ 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L,
+ 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L,
+ 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L,
+ 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L,
+ 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L,
+ 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L,
+ 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L,
+ 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL,
+ 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL,
+ 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L,
+ 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL,
+ 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL,
+ 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL,
+ 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L,
+ 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL,
+ 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL,
+ 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L,
+ 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L,
+ 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L,
+ 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L,
+ 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL,
+ 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL,
+ 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L,
+ 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L,
+ 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L,
+ 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL,
+ 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L,
+ 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L,
+ 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L,
+ 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL,
+ 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L,
+ 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L,
+ 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L,
+ 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL,
+ 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL,
+ 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L,
+ 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L,
+ 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L,
+ 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L,
+ 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL,
+ 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L,
+ 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL,
+ 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL,
+ 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L,
+ 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L,
+ 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL,
+ 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L,
+ 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL,
+ 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L,
+ 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL,
+ 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L,
+ 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L,
+ 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL,
+ 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L,
+ 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL,
+ 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L }
+};
+
+#endif /* !POLARSSL_BLOWFISH_ALT */
+#endif /* POLARSSL_BLOWFISH_C */
diff --git a/polarssl/blowfish.h b/polarssl/blowfish.h
new file mode 100644
index 0000000..0157f8e
--- /dev/null
+++ b/polarssl/blowfish.h
@@ -0,0 +1,171 @@
+/**
+ * \file blowfish.h
+ *
+ * \brief Blowfish block cipher
+ *
+ * Copyright (C) 2012-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_BLOWFISH_H
+#define POLARSSL_BLOWFISH_H
+
+#include "polarssl/config.h"
+
+#include
+
+#ifdef _MSC_VER
+#include
+typedef UINT32 uint32_t;
+#else
+#include
+#endif
+
+#define BLOWFISH_ENCRYPT 1
+#define BLOWFISH_DECRYPT 0
+#define BLOWFISH_MAX_KEY 448
+#define BLOWFISH_MIN_KEY 32
+#define BLOWFISH_ROUNDS 16 /* when increasing this value, make sure to extend the initialisation vectors */
+#define BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */
+
+#define POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */
+#define POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */
+
+#if !defined(POLARSSL_BLOWFISH_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief Blowfish context structure
+ */
+typedef struct
+{
+ uint32_t P[BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */
+ uint32_t S[4][256]; /*!< key dependent S-boxes */
+}
+blowfish_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Blowfish key schedule
+ *
+ * \param ctx Blowfish context to be initialized
+ * \param key encryption key
+ * \param keysize must be between 32 and 448 bits
+ *
+ * \return 0 if successful, or POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH
+ */
+int blowfish_setkey( blowfish_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief Blowfish-ECB block encryption/decryption
+ *
+ * \param ctx Blowfish context
+ * \param mode BLOWFISH_ENCRYPT or BLOWFISH_DECRYPT
+ * \param input 8-byte input block
+ * \param output 8-byte output block
+ *
+ * \return 0 if successful
+ */
+int blowfish_crypt_ecb( blowfish_context *ctx,
+ int mode,
+ const unsigned char input[BLOWFISH_BLOCKSIZE],
+ unsigned char output[BLOWFISH_BLOCKSIZE] );
+
+/**
+ * \brief Blowfish-CBC buffer encryption/decryption
+ * Length should be a multiple of the block
+ * size (8 bytes)
+ *
+ * \param ctx Blowfish context
+ * \param mode BLOWFISH_ENCRYPT or BLOWFISH_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH
+ */
+int blowfish_crypt_cbc( blowfish_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[BLOWFISH_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Blowfish CFB buffer encryption/decryption.
+ *
+ * both
+ * \param ctx Blowfish context
+ * \param mode BLOWFISH_ENCRYPT or BLOWFISH_DECRYPT
+ * \param length length of the input data
+ * \param iv_off offset in IV (updated after use)
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful
+ */
+int blowfish_crypt_cfb64( blowfish_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[BLOWFISH_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Blowfish-CTR buffer encryption/decryption
+ *
+ * Warning: You have to keep the maximum use of your counter in mind!
+ *
+ * \param length The length of the data
+ * \param nc_off The offset in the current stream_block (for resuming
+ * within current cipher stream). The offset pointer to
+ * should be 0 at the start of a stream.
+ * \param nonce_counter The 64-bit nonce and counter.
+ * \param stream_block The saved stream-block for resuming. Is overwritten
+ * by the function.
+ * \param input The input data stream
+ * \param output The output data stream
+ *
+ * \return 0 if successful
+ */
+int blowfish_crypt_ctr( blowfish_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[BLOWFISH_BLOCKSIZE],
+ unsigned char stream_block[BLOWFISH_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* POLARSSL_BLOWFISH_ALT */
+#include "polarssl/blowfish_alt.h"
+#endif /* POLARSSL_BLOWFISH_ALT */
+
+#endif /* blowfish.h */
diff --git a/polarssl/bn_mul.h b/polarssl/bn_mul.h
new file mode 100644
index 0000000..6d6c182
--- /dev/null
+++ b/polarssl/bn_mul.h
@@ -0,0 +1,864 @@
+/**
+ * \file bn_mul.h
+ *
+ * \brief Multi-precision integer library
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * Multiply source vector [s] with b, add result
+ * to destination vector [d] and set carry c.
+ *
+ * Currently supports:
+ *
+ * . IA-32 (386+) . AMD64 / EM64T
+ * . IA-32 (SSE2) . Motorola 68000
+ * . PowerPC, 32-bit . MicroBlaze
+ * . PowerPC, 64-bit . TriCore
+ * . SPARC v8 . ARM v3+
+ * . Alpha . MIPS32
+ * . C, longlong . C, generic
+ */
+#ifndef POLARSSL_BN_MUL_H
+#define POLARSSL_BN_MUL_H
+
+#include "polarssl/bignum.h"
+
+#if defined(POLARSSL_HAVE_ASM)
+
+#if defined(__GNUC__)
+#if defined(__i386__)
+
+#define MULADDC_INIT \
+ __asm__( " \
+ movl %%ebx, %0; \
+ movl %5, %%esi; \
+ movl %6, %%edi; \
+ movl %7, %%ecx; \
+ movl %8, %%ebx; \
+ "
+
+#define MULADDC_CORE \
+ " \
+ lodsl; \
+ mull %%ebx; \
+ addl %%ecx, %%eax; \
+ adcl $0, %%edx; \
+ addl (%%edi), %%eax; \
+ adcl $0, %%edx; \
+ movl %%edx, %%ecx; \
+ stosl; \
+ "
+
+#if defined(POLARSSL_HAVE_SSE2)
+
+#define MULADDC_HUIT \
+ " \
+ movd %%ecx, %%mm1; \
+ movd %%ebx, %%mm0; \
+ movd (%%edi), %%mm3; \
+ paddq %%mm3, %%mm1; \
+ movd (%%esi), %%mm2; \
+ pmuludq %%mm0, %%mm2; \
+ movd 4(%%esi), %%mm4; \
+ pmuludq %%mm0, %%mm4; \
+ movd 8(%%esi), %%mm6; \
+ pmuludq %%mm0, %%mm6; \
+ movd 12(%%esi), %%mm7; \
+ pmuludq %%mm0, %%mm7; \
+ paddq %%mm2, %%mm1; \
+ movd 4(%%edi), %%mm3; \
+ paddq %%mm4, %%mm3; \
+ movd 8(%%edi), %%mm5; \
+ paddq %%mm6, %%mm5; \
+ movd 12(%%edi), %%mm4; \
+ paddq %%mm4, %%mm7; \
+ movd %%mm1, (%%edi); \
+ movd 16(%%esi), %%mm2; \
+ pmuludq %%mm0, %%mm2; \
+ psrlq $32, %%mm1; \
+ movd 20(%%esi), %%mm4; \
+ pmuludq %%mm0, %%mm4; \
+ paddq %%mm3, %%mm1; \
+ movd 24(%%esi), %%mm6; \
+ pmuludq %%mm0, %%mm6; \
+ movd %%mm1, 4(%%edi); \
+ psrlq $32, %%mm1; \
+ movd 28(%%esi), %%mm3; \
+ pmuludq %%mm0, %%mm3; \
+ paddq %%mm5, %%mm1; \
+ movd 16(%%edi), %%mm5; \
+ paddq %%mm5, %%mm2; \
+ movd %%mm1, 8(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm7, %%mm1; \
+ movd 20(%%edi), %%mm5; \
+ paddq %%mm5, %%mm4; \
+ movd %%mm1, 12(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm2, %%mm1; \
+ movd 24(%%edi), %%mm5; \
+ paddq %%mm5, %%mm6; \
+ movd %%mm1, 16(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm4, %%mm1; \
+ movd 28(%%edi), %%mm5; \
+ paddq %%mm5, %%mm3; \
+ movd %%mm1, 20(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm6, %%mm1; \
+ movd %%mm1, 24(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm3, %%mm1; \
+ movd %%mm1, 28(%%edi); \
+ addl $32, %%edi; \
+ addl $32, %%esi; \
+ psrlq $32, %%mm1; \
+ movd %%mm1, %%ecx; \
+ "
+
+#define MULADDC_STOP \
+ " \
+ emms; \
+ movl %4, %%ebx; \
+ movl %%ecx, %1; \
+ movl %%edi, %2; \
+ movl %%esi, %3; \
+ " \
+ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "eax", "ecx", "edx", "esi", "edi" \
+ );
+
+#else
+
+#define MULADDC_STOP \
+ " \
+ movl %4, %%ebx; \
+ movl %%ecx, %1; \
+ movl %%edi, %2; \
+ movl %%esi, %3; \
+ " \
+ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "eax", "ecx", "edx", "esi", "edi" \
+ );
+#endif /* SSE2 */
+#endif /* i386 */
+
+#if defined(__amd64__) || defined (__x86_64__)
+
+#define MULADDC_INIT \
+ __asm__( "movq %0, %%rsi " :: "m" (s)); \
+ __asm__( "movq %0, %%rdi " :: "m" (d)); \
+ __asm__( "movq %0, %%rcx " :: "m" (c)); \
+ __asm__( "movq %0, %%rbx " :: "m" (b)); \
+ __asm__( "xorq %r8, %r8 " );
+
+#define MULADDC_CORE \
+ __asm__( "movq (%rsi),%rax " ); \
+ __asm__( "mulq %rbx " ); \
+ __asm__( "addq $8, %rsi " ); \
+ __asm__( "addq %rcx, %rax " ); \
+ __asm__( "movq %r8, %rcx " ); \
+ __asm__( "adcq $0, %rdx " ); \
+ __asm__( "nop " ); \
+ __asm__( "addq %rax, (%rdi) " ); \
+ __asm__( "adcq %rdx, %rcx " ); \
+ __asm__( "addq $8, %rdi " );
+
+#define MULADDC_STOP \
+ __asm__( "movq %%rcx, %0 " : "=m" (c)); \
+ __asm__( "movq %%rdi, %0 " : "=m" (d)); \
+ __asm__( "movq %%rsi, %0 " : "=m" (s) :: \
+ "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
+
+#endif /* AMD64 */
+
+#if defined(__mc68020__) || defined(__mcpu32__)
+
+#define MULADDC_INIT \
+ __asm__( "movl %0, %%a2 " :: "m" (s)); \
+ __asm__( "movl %0, %%a3 " :: "m" (d)); \
+ __asm__( "movl %0, %%d3 " :: "m" (c)); \
+ __asm__( "movl %0, %%d2 " :: "m" (b)); \
+ __asm__( "moveq #0, %d0 " );
+
+#define MULADDC_CORE \
+ __asm__( "movel %a2@+, %d1 " ); \
+ __asm__( "mulul %d2, %d4:%d1 " ); \
+ __asm__( "addl %d3, %d1 " ); \
+ __asm__( "addxl %d0, %d4 " ); \
+ __asm__( "moveq #0, %d3 " ); \
+ __asm__( "addl %d1, %a3@+ " ); \
+ __asm__( "addxl %d4, %d3 " );
+
+#define MULADDC_STOP \
+ __asm__( "movl %%d3, %0 " : "=m" (c)); \
+ __asm__( "movl %%a3, %0 " : "=m" (d)); \
+ __asm__( "movl %%a2, %0 " : "=m" (s) :: \
+ "d0", "d1", "d2", "d3", "d4", "a2", "a3" );
+
+#define MULADDC_HUIT \
+ __asm__( "movel %a2@+, %d1 " ); \
+ __asm__( "mulul %d2, %d4:%d1 " ); \
+ __asm__( "addxl %d3, %d1 " ); \
+ __asm__( "addxl %d0, %d4 " ); \
+ __asm__( "addl %d1, %a3@+ " ); \
+ __asm__( "movel %a2@+, %d1 " ); \
+ __asm__( "mulul %d2, %d3:%d1 " ); \
+ __asm__( "addxl %d4, %d1 " ); \
+ __asm__( "addxl %d0, %d3 " ); \
+ __asm__( "addl %d1, %a3@+ " ); \
+ __asm__( "movel %a2@+, %d1 " ); \
+ __asm__( "mulul %d2, %d4:%d1 " ); \
+ __asm__( "addxl %d3, %d1 " ); \
+ __asm__( "addxl %d0, %d4 " ); \
+ __asm__( "addl %d1, %a3@+ " ); \
+ __asm__( "movel %a2@+, %d1 " ); \
+ __asm__( "mulul %d2, %d3:%d1 " ); \
+ __asm__( "addxl %d4, %d1 " ); \
+ __asm__( "addxl %d0, %d3 " ); \
+ __asm__( "addl %d1, %a3@+ " ); \
+ __asm__( "movel %a2@+, %d1 " ); \
+ __asm__( "mulul %d2, %d4:%d1 " ); \
+ __asm__( "addxl %d3, %d1 " ); \
+ __asm__( "addxl %d0, %d4 " ); \
+ __asm__( "addl %d1, %a3@+ " ); \
+ __asm__( "movel %a2@+, %d1 " ); \
+ __asm__( "mulul %d2, %d3:%d1 " ); \
+ __asm__( "addxl %d4, %d1 " ); \
+ __asm__( "addxl %d0, %d3 " ); \
+ __asm__( "addl %d1, %a3@+ " ); \
+ __asm__( "movel %a2@+, %d1 " ); \
+ __asm__( "mulul %d2, %d4:%d1 " ); \
+ __asm__( "addxl %d3, %d1 " ); \
+ __asm__( "addxl %d0, %d4 " ); \
+ __asm__( "addl %d1, %a3@+ " ); \
+ __asm__( "movel %a2@+, %d1 " ); \
+ __asm__( "mulul %d2, %d3:%d1 " ); \
+ __asm__( "addxl %d4, %d1 " ); \
+ __asm__( "addxl %d0, %d3 " ); \
+ __asm__( "addl %d1, %a3@+ " ); \
+ __asm__( "addxl %d0, %d3 " );
+
+#endif /* MC68000 */
+
+#if defined(__powerpc__) || defined(__ppc__)
+#if defined(__powerpc64__) || defined(__ppc64__)
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT \
+ __asm__( "ld r3, %0 " :: "m" (s)); \
+ __asm__( "ld r4, %0 " :: "m" (d)); \
+ __asm__( "ld r5, %0 " :: "m" (c)); \
+ __asm__( "ld r6, %0 " :: "m" (b)); \
+ __asm__( "addi r3, r3, -8 " ); \
+ __asm__( "addi r4, r4, -8 " ); \
+ __asm__( "addic r5, r5, 0 " );
+
+#define MULADDC_CORE \
+ __asm__( "ldu r7, 8(r3) " ); \
+ __asm__( "mulld r8, r7, r6 " ); \
+ __asm__( "mulhdu r9, r7, r6 " ); \
+ __asm__( "adde r8, r8, r5 " ); \
+ __asm__( "ld r7, 8(r4) " ); \
+ __asm__( "addze r5, r9 " ); \
+ __asm__( "addc r8, r8, r7 " ); \
+ __asm__( "stdu r8, 8(r4) " );
+
+#define MULADDC_STOP \
+ __asm__( "addze r5, r5 " ); \
+ __asm__( "addi r4, r4, 8 " ); \
+ __asm__( "addi r3, r3, 8 " ); \
+ __asm__( "std r5, %0 " : "=m" (c)); \
+ __asm__( "std r4, %0 " : "=m" (d)); \
+ __asm__( "std r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#else
+
+#define MULADDC_INIT \
+ __asm__( "ld %%r3, %0 " :: "m" (s)); \
+ __asm__( "ld %%r4, %0 " :: "m" (d)); \
+ __asm__( "ld %%r5, %0 " :: "m" (c)); \
+ __asm__( "ld %%r6, %0 " :: "m" (b)); \
+ __asm__( "addi %r3, %r3, -8 " ); \
+ __asm__( "addi %r4, %r4, -8 " ); \
+ __asm__( "addic %r5, %r5, 0 " );
+
+#define MULADDC_CORE \
+ __asm__( "ldu %r7, 8(%r3) " ); \
+ __asm__( "mulld %r8, %r7, %r6 " ); \
+ __asm__( "mulhdu %r9, %r7, %r6 " ); \
+ __asm__( "adde %r8, %r8, %r5 " ); \
+ __asm__( "ld %r7, 8(%r4) " ); \
+ __asm__( "addze %r5, %r9 " ); \
+ __asm__( "addc %r8, %r8, %r7 " ); \
+ __asm__( "stdu %r8, 8(%r4) " );
+
+#define MULADDC_STOP \
+ __asm__( "addze %r5, %r5 " ); \
+ __asm__( "addi %r4, %r4, 8 " ); \
+ __asm__( "addi %r3, %r3, 8 " ); \
+ __asm__( "std %%r5, %0 " : "=m" (c)); \
+ __asm__( "std %%r4, %0 " : "=m" (d)); \
+ __asm__( "std %%r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#endif
+
+#else /* PPC32 */
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT \
+ __asm__( "lwz r3, %0 " :: "m" (s)); \
+ __asm__( "lwz r4, %0 " :: "m" (d)); \
+ __asm__( "lwz r5, %0 " :: "m" (c)); \
+ __asm__( "lwz r6, %0 " :: "m" (b)); \
+ __asm__( "addi r3, r3, -4 " ); \
+ __asm__( "addi r4, r4, -4 " ); \
+ __asm__( "addic r5, r5, 0 " );
+
+#define MULADDC_CORE \
+ __asm__( "lwzu r7, 4(r3) " ); \
+ __asm__( "mullw r8, r7, r6 " ); \
+ __asm__( "mulhwu r9, r7, r6 " ); \
+ __asm__( "adde r8, r8, r5 " ); \
+ __asm__( "lwz r7, 4(r4) " ); \
+ __asm__( "addze r5, r9 " ); \
+ __asm__( "addc r8, r8, r7 " ); \
+ __asm__( "stwu r8, 4(r4) " );
+
+#define MULADDC_STOP \
+ __asm__( "addze r5, r5 " ); \
+ __asm__( "addi r4, r4, 4 " ); \
+ __asm__( "addi r3, r3, 4 " ); \
+ __asm__( "stw r5, %0 " : "=m" (c)); \
+ __asm__( "stw r4, %0 " : "=m" (d)); \
+ __asm__( "stw r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#else
+
+#define MULADDC_INIT \
+ __asm__( "lwz %%r3, %0 " :: "m" (s)); \
+ __asm__( "lwz %%r4, %0 " :: "m" (d)); \
+ __asm__( "lwz %%r5, %0 " :: "m" (c)); \
+ __asm__( "lwz %%r6, %0 " :: "m" (b)); \
+ __asm__( "addi %r3, %r3, -4 " ); \
+ __asm__( "addi %r4, %r4, -4 " ); \
+ __asm__( "addic %r5, %r5, 0 " );
+
+#define MULADDC_CORE \
+ __asm__( "lwzu %r7, 4(%r3) " ); \
+ __asm__( "mullw %r8, %r7, %r6 " ); \
+ __asm__( "mulhwu %r9, %r7, %r6 " ); \
+ __asm__( "adde %r8, %r8, %r5 " ); \
+ __asm__( "lwz %r7, 4(%r4) " ); \
+ __asm__( "addze %r5, %r9 " ); \
+ __asm__( "addc %r8, %r8, %r7 " ); \
+ __asm__( "stwu %r8, 4(%r4) " );
+
+#define MULADDC_STOP \
+ __asm__( "addze %r5, %r5 " ); \
+ __asm__( "addi %r4, %r4, 4 " ); \
+ __asm__( "addi %r3, %r3, 4 " ); \
+ __asm__( "stw %%r5, %0 " : "=m" (c)); \
+ __asm__( "stw %%r4, %0 " : "=m" (d)); \
+ __asm__( "stw %%r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#endif
+
+#endif /* PPC32 */
+#endif /* PPC64 */
+
+#if defined(__sparc__) && defined(__sparc64__)
+
+#define MULADDC_INIT \
+ __asm__( \
+ " \
+ ldx %3, %%o0; \
+ ldx %4, %%o1; \
+ ld %5, %%o2; \
+ ld %6, %%o3; \
+ "
+
+#define MULADDC_CORE \
+ " \
+ ld [%%o0], %%o4; \
+ inc 4, %%o0; \
+ ld [%%o1], %%o5; \
+ umul %%o3, %%o4, %%o4; \
+ addcc %%o4, %%o2, %%o4; \
+ rd %%y, %%g1; \
+ addx %%g1, 0, %%g1; \
+ addcc %%o4, %%o5, %%o4; \
+ st %%o4, [%%o1]; \
+ addx %%g1, 0, %%o2; \
+ inc 4, %%o1; \
+ "
+
+#define MULADDC_STOP \
+ " \
+ st %%o2, %0; \
+ stx %%o1, %1; \
+ stx %%o0, %2; \
+ " \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "g1", "o0", "o1", "o2", "o3", "o4", \
+ "o5" \
+ );
+#endif /* SPARCv9 */
+
+#if defined(__sparc__) && !defined(__sparc64__)
+
+#define MULADDC_INIT \
+ __asm__( \
+ " \
+ ld %3, %%o0; \
+ ld %4, %%o1; \
+ ld %5, %%o2; \
+ ld %6, %%o3; \
+ "
+
+#define MULADDC_CORE \
+ " \
+ ld [%%o0], %%o4; \
+ inc 4, %%o0; \
+ ld [%%o1], %%o5; \
+ umul %%o3, %%o4, %%o4; \
+ addcc %%o4, %%o2, %%o4; \
+ rd %%y, %%g1; \
+ addx %%g1, 0, %%g1; \
+ addcc %%o4, %%o5, %%o4; \
+ st %%o4, [%%o1]; \
+ addx %%g1, 0, %%o2; \
+ inc 4, %%o1; \
+ "
+
+#define MULADDC_STOP \
+ " \
+ st %%o2, %0; \
+ st %%o1, %1; \
+ st %%o0, %2; \
+ " \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "g1", "o0", "o1", "o2", "o3", "o4", \
+ "o5" \
+ );
+
+#endif /* SPARCv8 */
+
+#if defined(__microblaze__) || defined(microblaze)
+
+#define MULADDC_INIT \
+ __asm__( "lwi r3, %0 " :: "m" (s)); \
+ __asm__( "lwi r4, %0 " :: "m" (d)); \
+ __asm__( "lwi r5, %0 " :: "m" (c)); \
+ __asm__( "lwi r6, %0 " :: "m" (b)); \
+ __asm__( "andi r7, r6, 0xffff" ); \
+ __asm__( "bsrli r6, r6, 16 " );
+
+#define MULADDC_CORE \
+ __asm__( "lhui r8, r3, 0 " ); \
+ __asm__( "addi r3, r3, 2 " ); \
+ __asm__( "lhui r9, r3, 0 " ); \
+ __asm__( "addi r3, r3, 2 " ); \
+ __asm__( "mul r10, r9, r6 " ); \
+ __asm__( "mul r11, r8, r7 " ); \
+ __asm__( "mul r12, r9, r7 " ); \
+ __asm__( "mul r13, r8, r6 " ); \
+ __asm__( "bsrli r8, r10, 16 " ); \
+ __asm__( "bsrli r9, r11, 16 " ); \
+ __asm__( "add r13, r13, r8 " ); \
+ __asm__( "add r13, r13, r9 " ); \
+ __asm__( "bslli r10, r10, 16 " ); \
+ __asm__( "bslli r11, r11, 16 " ); \
+ __asm__( "add r12, r12, r10 " ); \
+ __asm__( "addc r13, r13, r0 " ); \
+ __asm__( "add r12, r12, r11 " ); \
+ __asm__( "addc r13, r13, r0 " ); \
+ __asm__( "lwi r10, r4, 0 " ); \
+ __asm__( "add r12, r12, r10 " ); \
+ __asm__( "addc r13, r13, r0 " ); \
+ __asm__( "add r12, r12, r5 " ); \
+ __asm__( "addc r5, r13, r0 " ); \
+ __asm__( "swi r12, r4, 0 " ); \
+ __asm__( "addi r4, r4, 4 " );
+
+#define MULADDC_STOP \
+ __asm__( "swi r5, %0 " : "=m" (c)); \
+ __asm__( "swi r4, %0 " : "=m" (d)); \
+ __asm__( "swi r3, %0 " : "=m" (s) :: \
+ "r3", "r4" , "r5" , "r6" , "r7" , "r8" , \
+ "r9", "r10", "r11", "r12", "r13" );
+
+#endif /* MicroBlaze */
+
+#if defined(__tricore__)
+
+#define MULADDC_INIT \
+ __asm__( "ld.a %%a2, %0 " :: "m" (s)); \
+ __asm__( "ld.a %%a3, %0 " :: "m" (d)); \
+ __asm__( "ld.w %%d4, %0 " :: "m" (c)); \
+ __asm__( "ld.w %%d1, %0 " :: "m" (b)); \
+ __asm__( "xor %d5, %d5 " );
+
+#define MULADDC_CORE \
+ __asm__( "ld.w %d0, [%a2+] " ); \
+ __asm__( "madd.u %e2, %e4, %d0, %d1 " ); \
+ __asm__( "ld.w %d0, [%a3] " ); \
+ __asm__( "addx %d2, %d2, %d0 " ); \
+ __asm__( "addc %d3, %d3, 0 " ); \
+ __asm__( "mov %d4, %d3 " ); \
+ __asm__( "st.w [%a3+], %d2 " );
+
+#define MULADDC_STOP \
+ __asm__( "st.w %0, %%d4 " : "=m" (c)); \
+ __asm__( "st.a %0, %%a3 " : "=m" (d)); \
+ __asm__( "st.a %0, %%a2 " : "=m" (s) :: \
+ "d0", "d1", "e2", "d4", "a2", "a3" );
+
+#endif /* TriCore */
+
+#if defined(__arm__)
+
+#if defined(__thumb__) && !defined(__thumb2__)
+
+#define MULADDC_INIT \
+ __asm__( \
+ " \
+ ldr r0, %3; \
+ ldr r1, %4; \
+ ldr r2, %5; \
+ ldr r3, %6; \
+ lsr r7, r3, #16; \
+ mov r9, r7; \
+ lsl r7, r3, #16; \
+ lsr r7, r7, #16; \
+ mov r8, r7; \
+ "
+
+#define MULADDC_CORE \
+ " \
+ ldmia r0!, {r6}; \
+ lsr r7, r6, #16; \
+ lsl r6, r6, #16; \
+ lsr r6, r6, #16; \
+ mov r4, r8; \
+ mul r4, r6; \
+ mov r3, r9; \
+ mul r6, r3; \
+ mov r5, r9; \
+ mul r5, r7; \
+ mov r3, r8; \
+ mul r7, r3; \
+ lsr r3, r6, #16; \
+ add r5, r5, r3; \
+ lsr r3, r7, #16; \
+ add r5, r5, r3; \
+ add r4, r4, r2; \
+ mov r2, #0; \
+ adc r5, r2; \
+ lsl r3, r6, #16; \
+ add r4, r4, r3; \
+ adc r5, r2; \
+ lsl r3, r7, #16; \
+ add r4, r4, r3; \
+ adc r5, r2; \
+ ldr r3, [r1]; \
+ add r4, r4, r3; \
+ adc r2, r5; \
+ stmia r1!, {r4}; \
+ "
+
+#define MULADDC_STOP \
+ " \
+ str r2, %0; \
+ str r1, %1; \
+ str r0, %2; \
+ " \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "r0", "r1", "r2", "r3", "r4", "r5", \
+ "r6", "r7", "r8", "r9", "cc" \
+ );
+
+#else
+
+#define MULADDC_INIT \
+ __asm__( \
+ " \
+ ldr r0, %3; \
+ ldr r1, %4; \
+ ldr r2, %5; \
+ ldr r3, %6; \
+ "
+
+#define MULADDC_CORE \
+ " \
+ ldr r4, [r0], #4; \
+ mov r5, #0; \
+ ldr r6, [r1]; \
+ umlal r2, r5, r3, r4; \
+ adds r7, r6, r2; \
+ adc r2, r5, #0; \
+ str r7, [r1], #4; \
+ "
+
+#define MULADDC_STOP \
+ " \
+ str r2, %0; \
+ str r1, %1; \
+ str r0, %2; \
+ " \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "r0", "r1", "r2", "r3", "r4", "r5", \
+ "r6", "r7", "cc" \
+ );
+
+#endif /* Thumb */
+
+#endif /* ARMv3 */
+
+#if defined(__alpha__)
+
+#define MULADDC_INIT \
+ __asm__( "ldq $1, %0 " :: "m" (s)); \
+ __asm__( "ldq $2, %0 " :: "m" (d)); \
+ __asm__( "ldq $3, %0 " :: "m" (c)); \
+ __asm__( "ldq $4, %0 " :: "m" (b));
+
+#define MULADDC_CORE \
+ __asm__( "ldq $6, 0($1) " ); \
+ __asm__( "addq $1, 8, $1 " ); \
+ __asm__( "mulq $6, $4, $7 " ); \
+ __asm__( "umulh $6, $4, $6 " ); \
+ __asm__( "addq $7, $3, $7 " ); \
+ __asm__( "cmpult $7, $3, $3 " ); \
+ __asm__( "ldq $5, 0($2) " ); \
+ __asm__( "addq $7, $5, $7 " ); \
+ __asm__( "cmpult $7, $5, $5 " ); \
+ __asm__( "stq $7, 0($2) " ); \
+ __asm__( "addq $2, 8, $2 " ); \
+ __asm__( "addq $6, $3, $3 " ); \
+ __asm__( "addq $5, $3, $3 " );
+
+#define MULADDC_STOP \
+ __asm__( "stq $3, %0 " : "=m" (c)); \
+ __asm__( "stq $2, %0 " : "=m" (d)); \
+ __asm__( "stq $1, %0 " : "=m" (s) :: \
+ "$1", "$2", "$3", "$4", "$5", "$6", "$7" );
+
+#endif /* Alpha */
+
+#if defined(__mips__)
+
+#define MULADDC_INIT \
+ __asm__( "lw $10, %0 " :: "m" (s)); \
+ __asm__( "lw $11, %0 " :: "m" (d)); \
+ __asm__( "lw $12, %0 " :: "m" (c)); \
+ __asm__( "lw $13, %0 " :: "m" (b));
+
+#define MULADDC_CORE \
+ __asm__( "lw $14, 0($10) " ); \
+ __asm__( "multu $13, $14 " ); \
+ __asm__( "addi $10, $10, 4 " ); \
+ __asm__( "mflo $14 " ); \
+ __asm__( "mfhi $9 " ); \
+ __asm__( "addu $14, $12, $14 " ); \
+ __asm__( "lw $15, 0($11) " ); \
+ __asm__( "sltu $12, $14, $12 " ); \
+ __asm__( "addu $15, $14, $15 " ); \
+ __asm__( "sltu $14, $15, $14 " ); \
+ __asm__( "addu $12, $12, $9 " ); \
+ __asm__( "sw $15, 0($11) " ); \
+ __asm__( "addu $12, $12, $14 " ); \
+ __asm__( "addi $11, $11, 4 " );
+
+#define MULADDC_STOP \
+ __asm__( "sw $12, %0 " : "=m" (c)); \
+ __asm__( "sw $11, %0 " : "=m" (d)); \
+ __asm__( "sw $10, %0 " : "=m" (s) :: \
+ "$9", "$10", "$11", "$12", "$13", "$14", "$15" );
+
+#endif /* MIPS */
+#endif /* GNUC */
+
+#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+
+#define MULADDC_INIT \
+ ____asm__ mov esi, s \
+ ____asm__ mov edi, d \
+ ____asm__ mov ecx, c \
+ ____asm__ mov ebx, b
+
+#define MULADDC_CORE \
+ ____asm__ lodsd \
+ ____asm__ mul ebx \
+ ____asm__ add eax, ecx \
+ ____asm__ adc edx, 0 \
+ ____asm__ add eax, [edi] \
+ ____asm__ adc edx, 0 \
+ ____asm__ mov ecx, edx \
+ ____asm__ stosd
+
+#if defined(POLARSSL_HAVE_SSE2)
+
+#define EMIT ____asm__ _emit
+
+#define MULADDC_HUIT \
+ EMIT 0x0F EMIT 0x6E EMIT 0xC9 \
+ EMIT 0x0F EMIT 0x6E EMIT 0xC3 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x1F \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x6E EMIT 0x16 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
+ EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xDC \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xEE \
+ EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xFC \
+ EMIT 0x0F EMIT 0x7E EMIT 0x0F \
+ EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCD \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCF \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCC \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xDD \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCE \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \
+ EMIT 0x83 EMIT 0xC7 EMIT 0x20 \
+ EMIT 0x83 EMIT 0xC6 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x7E EMIT 0xC9
+
+#define MULADDC_STOP \
+ EMIT 0x0F EMIT 0x77 \
+ ____asm__ mov c, ecx \
+ ____asm__ mov d, edi \
+ ____asm__ mov s, esi \
+
+#else
+
+#define MULADDC_STOP \
+ ____asm__ mov c, ecx \
+ ____asm__ mov d, edi \
+ ____asm__ mov s, esi \
+
+#endif /* SSE2 */
+#endif /* MSVC */
+
+#endif /* POLARSSL_HAVE_ASM */
+
+#if !defined(MULADDC_CORE)
+#if defined(POLARSSL_HAVE_UDBL)
+
+#define MULADDC_INIT \
+{ \
+ t_udbl r; \
+ t_uint r0, r1;
+
+#define MULADDC_CORE \
+ r = *(s++) * (t_udbl) b; \
+ r0 = r; \
+ r1 = r >> biL; \
+ r0 += c; r1 += (r0 < c); \
+ r0 += *d; r1 += (r0 < *d); \
+ c = r1; *(d++) = r0;
+
+#define MULADDC_STOP \
+}
+
+#else
+#define MULADDC_INIT \
+{ \
+ t_uint s0, s1, b0, b1; \
+ t_uint r0, r1, rx, ry; \
+ b0 = ( b << biH ) >> biH; \
+ b1 = ( b >> biH );
+
+#define MULADDC_CORE \
+ s0 = ( *s << biH ) >> biH; \
+ s1 = ( *s >> biH ); s++; \
+ rx = s0 * b1; r0 = s0 * b0; \
+ ry = s1 * b0; r1 = s1 * b1; \
+ r1 += ( rx >> biH ); \
+ r1 += ( ry >> biH ); \
+ rx <<= biH; ry <<= biH; \
+ r0 += rx; r1 += (r0 < rx); \
+ r0 += ry; r1 += (r0 < ry); \
+ r0 += c; r1 += (r0 < c); \
+ r0 += *d; r1 += (r0 < *d); \
+ c = r1; *(d++) = r0;
+
+#define MULADDC_STOP \
+}
+
+#endif /* C (generic) */
+#endif /* C (longlong) */
+
+#endif /* bn_mul.h */
diff --git a/polarssl/camellia.c b/polarssl/camellia.c
new file mode 100644
index 0000000..bb87875
--- /dev/null
+++ b/polarssl/camellia.c
@@ -0,0 +1,1035 @@
+/*
+ * Camellia implementation
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The Camellia block cipher was designed by NTT and Mitsubishi Electric
+ * Corporation.
+ *
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_CAMELLIA_C)
+
+#include "polarssl/camellia.h"
+
+#if !defined(POLARSSL_CAMELLIA_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+static const unsigned char SIGMA_CHARS[6][8] =
+{
+ { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b },
+ { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 },
+ { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe },
+ { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c },
+ { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d },
+ { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd }
+};
+
+#if defined(POLARSSL_CAMELLIA_SMALL_MEMORY)
+
+static const unsigned char FSb[256] =
+{
+ 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65,
+ 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189,
+ 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26,
+ 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77,
+ 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153,
+ 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215,
+ 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34,
+ 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80,
+ 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210,
+ 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148,
+ 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226,
+ 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46,
+ 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89,
+ 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250,
+ 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164,
+ 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158
+};
+
+#define SBOX1(n) FSb[(n)]
+#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff)
+#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff)
+#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff]
+
+#else
+
+static const unsigned char FSb[256] =
+{
+ 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65,
+ 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189,
+ 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26,
+ 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77,
+ 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153,
+ 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215,
+ 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34,
+ 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80,
+ 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210,
+ 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148,
+ 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226,
+ 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46,
+ 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89,
+ 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250,
+ 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164,
+ 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158
+};
+
+static const unsigned char FSb2[256] =
+{
+ 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130,
+ 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123,
+ 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52,
+ 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154,
+ 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51,
+ 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175,
+ 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68,
+ 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160,
+ 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165,
+ 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41,
+ 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197,
+ 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92,
+ 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178,
+ 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245,
+ 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73,
+ 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61
+};
+
+static const unsigned char FSb3[256] =
+{
+ 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160,
+ 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222,
+ 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13,
+ 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166,
+ 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204,
+ 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235,
+ 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17,
+ 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40,
+ 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105,
+ 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74,
+ 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113,
+ 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23,
+ 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172,
+ 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125,
+ 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82,
+ 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79
+};
+
+static const unsigned char FSb4[256] =
+{
+ 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146,
+ 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108,
+ 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4,
+ 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105,
+ 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221,
+ 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99,
+ 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141,
+ 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128,
+ 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189,
+ 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77,
+ 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215,
+ 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80,
+ 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148,
+ 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46,
+ 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250,
+ 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158
+};
+
+#define SBOX1(n) FSb[(n)]
+#define SBOX2(n) FSb2[(n)]
+#define SBOX3(n) FSb3[(n)]
+#define SBOX4(n) FSb4[(n)]
+
+#endif
+
+static const unsigned char shifts[2][4][4] =
+{
+ {
+ { 1, 1, 1, 1 }, /* KL */
+ { 0, 0, 0, 0 }, /* KR */
+ { 1, 1, 1, 1 }, /* KA */
+ { 0, 0, 0, 0 } /* KB */
+ },
+ {
+ { 1, 0, 1, 1 }, /* KL */
+ { 1, 1, 0, 1 }, /* KR */
+ { 1, 1, 1, 0 }, /* KA */
+ { 1, 1, 0, 1 } /* KB */
+ }
+};
+
+static const signed char indexes[2][4][20] =
+{
+ {
+ { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39,
+ 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */
+ { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17,
+ 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */
+ },
+ {
+ { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1,
+ -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */
+ { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17,
+ 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */
+ { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59,
+ 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */
+ { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21,
+ 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */
+ }
+};
+
+static const signed char transposes[2][20] =
+{
+ {
+ 21, 22, 23, 20,
+ -1, -1, -1, -1,
+ 18, 19, 16, 17,
+ 11, 8, 9, 10,
+ 15, 12, 13, 14
+ },
+ {
+ 25, 26, 27, 24,
+ 29, 30, 31, 28,
+ 18, 19, 16, 17,
+ -1, -1, -1, -1,
+ -1, -1, -1, -1
+ }
+};
+
+/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */
+#define ROTL(DEST, SRC, SHIFT) \
+{ \
+ (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \
+ (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \
+ (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \
+ (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \
+}
+
+#define FL(XL, XR, KL, KR) \
+{ \
+ (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \
+ (XL) = ((XR) | (KR)) ^ (XL); \
+}
+
+#define FLInv(YL, YR, KL, KR) \
+{ \
+ (YL) = ((YR) | (KR)) ^ (YL); \
+ (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \
+}
+
+#define SHIFT_AND_PLACE(INDEX, OFFSET) \
+{ \
+ TK[0] = KC[(OFFSET) * 4 + 0]; \
+ TK[1] = KC[(OFFSET) * 4 + 1]; \
+ TK[2] = KC[(OFFSET) * 4 + 2]; \
+ TK[3] = KC[(OFFSET) * 4 + 3]; \
+ \
+ for ( i = 1; i <= 4; i++ ) \
+ if (shifts[(INDEX)][(OFFSET)][i -1]) \
+ ROTL(TK + i * 4, TK, (15 * i) % 32); \
+ \
+ for ( i = 0; i < 20; i++ ) \
+ if (indexes[(INDEX)][(OFFSET)][i] != -1) { \
+ RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \
+ } \
+}
+
+static void camellia_feistel(const uint32_t x[2], const uint32_t k[2], uint32_t z[2])
+{
+ uint32_t I0, I1;
+ I0 = x[0] ^ k[0];
+ I1 = x[1] ^ k[1];
+
+ I0 = (SBOX1((I0 >> 24) & 0xFF) << 24) |
+ (SBOX2((I0 >> 16) & 0xFF) << 16) |
+ (SBOX3((I0 >> 8) & 0xFF) << 8) |
+ (SBOX4((I0 ) & 0xFF) );
+ I1 = (SBOX2((I1 >> 24) & 0xFF) << 24) |
+ (SBOX3((I1 >> 16) & 0xFF) << 16) |
+ (SBOX4((I1 >> 8) & 0xFF) << 8) |
+ (SBOX1((I1 ) & 0xFF) );
+
+ I0 ^= (I1 << 8) | (I1 >> 24);
+ I1 ^= (I0 << 16) | (I0 >> 16);
+ I0 ^= (I1 >> 8) | (I1 << 24);
+ I1 ^= (I0 >> 8) | (I0 << 24);
+
+ z[0] ^= I1;
+ z[1] ^= I0;
+}
+
+/*
+ * Camellia key schedule (encryption)
+ */
+int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+ int idx;
+ size_t i;
+ uint32_t *RK;
+ unsigned char t[64];
+ uint32_t SIGMA[6][2];
+ uint32_t KC[16];
+ uint32_t TK[20];
+
+ RK = ctx->rk;
+
+ memset(t, 0, 64);
+ memset(RK, 0, sizeof(ctx->rk));
+
+ switch( keysize )
+ {
+ case 128: ctx->nr = 3; idx = 0; break;
+ case 192:
+ case 256: ctx->nr = 4; idx = 1; break;
+ default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
+ }
+
+ for( i = 0; i < keysize / 8; ++i)
+ t[i] = key[i];
+
+ if (keysize == 192) {
+ for (i = 0; i < 8; i++)
+ t[24 + i] = ~t[16 + i];
+ }
+
+ /*
+ * Prepare SIGMA values
+ */
+ for (i = 0; i < 6; i++) {
+ GET_UINT32_BE(SIGMA[i][0], SIGMA_CHARS[i], 0);
+ GET_UINT32_BE(SIGMA[i][1], SIGMA_CHARS[i], 4);
+ }
+
+ /*
+ * Key storage in KC
+ * Order: KL, KR, KA, KB
+ */
+ memset(KC, 0, sizeof(KC));
+
+ /* Store KL, KR */
+ for (i = 0; i < 8; i++)
+ GET_UINT32_BE(KC[i], t, i * 4);
+
+ /* Generate KA */
+ for( i = 0; i < 4; ++i)
+ KC[8 + i] = KC[i] ^ KC[4 + i];
+
+ camellia_feistel(KC + 8, SIGMA[0], KC + 10);
+ camellia_feistel(KC + 10, SIGMA[1], KC + 8);
+
+ for( i = 0; i < 4; ++i)
+ KC[8 + i] ^= KC[i];
+
+ camellia_feistel(KC + 8, SIGMA[2], KC + 10);
+ camellia_feistel(KC + 10, SIGMA[3], KC + 8);
+
+ if (keysize > 128) {
+ /* Generate KB */
+ for( i = 0; i < 4; ++i)
+ KC[12 + i] = KC[4 + i] ^ KC[8 + i];
+
+ camellia_feistel(KC + 12, SIGMA[4], KC + 14);
+ camellia_feistel(KC + 14, SIGMA[5], KC + 12);
+ }
+
+ /*
+ * Generating subkeys
+ */
+
+ /* Manipulating KL */
+ SHIFT_AND_PLACE(idx, 0);
+
+ /* Manipulating KR */
+ if (keysize > 128) {
+ SHIFT_AND_PLACE(idx, 1);
+ }
+
+ /* Manipulating KA */
+ SHIFT_AND_PLACE(idx, 2);
+
+ /* Manipulating KB */
+ if (keysize > 128) {
+ SHIFT_AND_PLACE(idx, 3);
+ }
+
+ /* Do transpositions */
+ for ( i = 0; i < 20; i++ ) {
+ if (transposes[idx][i] != -1) {
+ RK[32 + 12 * idx + i] = RK[transposes[idx][i]];
+ }
+ }
+
+ return( 0 );
+}
+
+/*
+ * Camellia key schedule (decryption)
+ */
+int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+ int idx;
+ size_t i;
+ camellia_context cty;
+ uint32_t *RK;
+ uint32_t *SK;
+ int ret;
+
+ switch( keysize )
+ {
+ case 128: ctx->nr = 3; idx = 0; break;
+ case 192:
+ case 256: ctx->nr = 4; idx = 1; break;
+ default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
+ }
+
+ RK = ctx->rk;
+
+ ret = camellia_setkey_enc(&cty, key, keysize);
+ if( ret != 0 )
+ return( ret );
+
+ SK = cty.rk + 24 * 2 + 8 * idx * 2;
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+ for (i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4)
+ {
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ }
+
+ SK -= 2;
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+ memset( &cty, 0, sizeof( camellia_context ) );
+
+ return( 0 );
+}
+
+/*
+ * Camellia-ECB block encryption/decryption
+ */
+int camellia_crypt_ecb( camellia_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ int NR;
+ uint32_t *RK, X[4];
+
+ ( (void) mode );
+
+ NR = ctx->nr;
+ RK = ctx->rk;
+
+ GET_UINT32_BE( X[0], input, 0 );
+ GET_UINT32_BE( X[1], input, 4 );
+ GET_UINT32_BE( X[2], input, 8 );
+ GET_UINT32_BE( X[3], input, 12 );
+
+ X[0] ^= *RK++;
+ X[1] ^= *RK++;
+ X[2] ^= *RK++;
+ X[3] ^= *RK++;
+
+ while (NR) {
+ --NR;
+ camellia_feistel(X, RK, X + 2);
+ RK += 2;
+ camellia_feistel(X + 2, RK, X);
+ RK += 2;
+ camellia_feistel(X, RK, X + 2);
+ RK += 2;
+ camellia_feistel(X + 2, RK, X);
+ RK += 2;
+ camellia_feistel(X, RK, X + 2);
+ RK += 2;
+ camellia_feistel(X + 2, RK, X);
+ RK += 2;
+
+ if (NR) {
+ FL(X[0], X[1], RK[0], RK[1]);
+ RK += 2;
+ FLInv(X[2], X[3], RK[0], RK[1]);
+ RK += 2;
+ }
+ }
+
+ X[2] ^= *RK++;
+ X[3] ^= *RK++;
+ X[0] ^= *RK++;
+ X[1] ^= *RK++;
+
+ PUT_UINT32_BE( X[2], output, 0 );
+ PUT_UINT32_BE( X[3], output, 4 );
+ PUT_UINT32_BE( X[0], output, 8 );
+ PUT_UINT32_BE( X[1], output, 12 );
+
+ return( 0 );
+}
+
+/*
+ * Camellia-CBC buffer encryption/decryption
+ */
+int camellia_crypt_cbc( camellia_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[16];
+
+ if( length % 16 )
+ return( POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH );
+
+ if( mode == CAMELLIA_DECRYPT )
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 16 );
+ camellia_crypt_ecb( ctx, mode, input, output );
+
+ for( i = 0; i < 16; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 16 );
+
+ input += 16;
+ output += 16;
+ length -= 16;
+ }
+ }
+ else
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 16; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ camellia_crypt_ecb( ctx, mode, output, output );
+ memcpy( iv, output, 16 );
+
+ input += 16;
+ output += 16;
+ length -= 16;
+ }
+ }
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * Camellia-CFB128 buffer encryption/decryption
+ */
+int camellia_crypt_cfb128( camellia_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c;
+ size_t n = *iv_off;
+
+ if( mode == CAMELLIA_DECRYPT )
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv );
+
+ c = *input++;
+ *output++ = (unsigned char)( c ^ iv[n] );
+ iv[n] = (unsigned char) c;
+
+ n = (n + 1) & 0x0F;
+ }
+ }
+ else
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv );
+
+ iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+ n = (n + 1) & 0x0F;
+ }
+ }
+
+ *iv_off = n;
+
+ return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * Camellia-CTR buffer encryption/decryption
+ */
+int camellia_crypt_ctr( camellia_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c, i;
+ size_t n = *nc_off;
+
+ while( length-- )
+ {
+ if( n == 0 ) {
+ camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, nonce_counter, stream_block );
+
+ for( i = 16; i > 0; i-- )
+ if( ++nonce_counter[i - 1] != 0 )
+ break;
+ }
+ c = *input++;
+ *output++ = (unsigned char)( c ^ stream_block[n] );
+
+ n = (n + 1) & 0x0F;
+ }
+
+ *nc_off = n;
+
+ return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+#endif /* !POLARSSL_CAMELLIA_ALT */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include
+
+/*
+ * Camellia test vectors from:
+ *
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html:
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt
+ * (For each bitlength: Key 0, Nr 39)
+ */
+#define CAMELLIA_TESTS_ECB 2
+
+static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] =
+{
+ {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+ },
+ {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+ },
+ {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+ },
+};
+
+static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] =
+{
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+ { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] =
+{
+ {
+ { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
+ 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
+ { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE,
+ 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 }
+ },
+ {
+ { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
+ 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
+ { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9,
+ 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 }
+ },
+ {
+ { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
+ 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
+ { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C,
+ 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 }
+ }
+};
+
+#define CAMELLIA_TESTS_CBC 3
+
+static const unsigned char camellia_test_cbc_key[3][32] =
+{
+ { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
+ ,
+ { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+ 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+ 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }
+ ,
+ { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+ 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+ 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+ 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char camellia_test_cbc_iv[16] =
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }
+;
+
+static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] =
+{
+ { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+ 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A },
+ { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+ 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 },
+ { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+ 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF }
+
+};
+
+static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] =
+{
+ {
+ { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0,
+ 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB },
+ { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78,
+ 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 },
+ { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B,
+ 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 }
+ },
+ {
+ { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2,
+ 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 },
+ { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42,
+ 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 },
+ { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8,
+ 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 }
+ },
+ {
+ { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A,
+ 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA },
+ { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40,
+ 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 },
+ { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA,
+ 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 }
+ }
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * Camellia-CTR test vectors from:
+ *
+ * http://www.faqs.org/rfcs/rfc5528.html
+ */
+
+static const unsigned char camellia_test_ctr_key[3][16] =
+{
+ { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+ 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
+ { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
+ 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
+ { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+ 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
+};
+
+static const unsigned char camellia_test_ctr_nonce_counter[3][16] =
+{
+ { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
+ 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
+ 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
+};
+
+static const unsigned char camellia_test_ctr_pt[3][48] =
+{
+ { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+ 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23 }
+};
+
+static const unsigned char camellia_test_ctr_ct[3][48] =
+{
+ { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A,
+ 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F },
+ { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4,
+ 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44,
+ 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7,
+ 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 },
+ { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88,
+ 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73,
+ 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1,
+ 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD,
+ 0xDF, 0x50, 0x86, 0x96 }
+};
+
+static const int camellia_test_ctr_len[3] =
+ { 16, 32, 36 };
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+/*
+ * Checkup routine
+ */
+int camellia_self_test( int verbose )
+{
+ int i, j, u, v;
+ unsigned char key[32];
+ unsigned char buf[64];
+ unsigned char src[16];
+ unsigned char dst[16];
+ unsigned char iv[16];
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ size_t offset, len;
+ unsigned char nonce_counter[16];
+ unsigned char stream_block[16];
+#endif
+
+ camellia_context ctx;
+
+ memset( key, 0, 32 );
+
+ for (j = 0; j < 6; j++) {
+ u = j >> 1;
+ v = j & 1;
+
+ if( verbose != 0 )
+ printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64,
+ (v == CAMELLIA_DECRYPT) ? "dec" : "enc");
+
+ for (i = 0; i < CAMELLIA_TESTS_ECB; i++ ) {
+ memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u);
+
+ if (v == CAMELLIA_DECRYPT) {
+ camellia_setkey_dec(&ctx, key, 128 + u * 64);
+ memcpy(src, camellia_test_ecb_cipher[u][i], 16);
+ memcpy(dst, camellia_test_ecb_plain[i], 16);
+ } else { /* CAMELLIA_ENCRYPT */
+ camellia_setkey_enc(&ctx, key, 128 + u * 64);
+ memcpy(src, camellia_test_ecb_plain[i], 16);
+ memcpy(dst, camellia_test_ecb_cipher[u][i], 16);
+ }
+
+ camellia_crypt_ecb(&ctx, v, src, buf);
+
+ if( memcmp( buf, dst, 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ /*
+ * CBC mode
+ */
+ for( j = 0; j < 6; j++ )
+ {
+ u = j >> 1;
+ v = j & 1;
+
+ if( verbose != 0 )
+ printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64,
+ ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( src, camellia_test_cbc_iv, 16);
+ memcpy( dst, camellia_test_cbc_iv, 16);
+ memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u);
+
+ if (v == CAMELLIA_DECRYPT) {
+ camellia_setkey_dec(&ctx, key, 128 + u * 64);
+ } else {
+ camellia_setkey_enc(&ctx, key, 128 + u * 64);
+ }
+
+ for (i = 0; i < CAMELLIA_TESTS_CBC; i++ ) {
+
+ if (v == CAMELLIA_DECRYPT) {
+ memcpy( iv , src, 16 );
+ memcpy(src, camellia_test_cbc_cipher[u][i], 16);
+ memcpy(dst, camellia_test_cbc_plain[i], 16);
+ } else { /* CAMELLIA_ENCRYPT */
+ memcpy( iv , dst, 16 );
+ memcpy(src, camellia_test_cbc_plain[i], 16);
+ memcpy(dst, camellia_test_cbc_cipher[u][i], 16);
+ }
+
+ camellia_crypt_cbc(&ctx, v, 16, iv, src, buf);
+
+ if( memcmp( buf, dst, 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ /*
+ * CTR mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " CAMELLIA-CTR-128 (%s): ",
+ ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 );
+ memcpy( key, camellia_test_ctr_key[u], 16 );
+
+ offset = 0;
+ camellia_setkey_enc( &ctx, key, 128 );
+
+ if( v == CAMELLIA_DECRYPT )
+ {
+ len = camellia_test_ctr_len[u];
+ memcpy( buf, camellia_test_ctr_ct[u], len );
+
+ camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+
+ if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ len = camellia_test_ctr_len[u];
+ memcpy( buf, camellia_test_ctr_pt[u], len );
+
+ camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+
+ if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+ return ( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/camellia.h b/polarssl/camellia.h
new file mode 100644
index 0000000..3bd3bc3
--- /dev/null
+++ b/polarssl/camellia.h
@@ -0,0 +1,200 @@
+/**
+ * \file camellia.h
+ *
+ * \brief Camellia block cipher
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CAMELLIA_H
+#define POLARSSL_CAMELLIA_H
+
+#include "polarssl/config.h"
+
+#include
+
+#ifdef _MSC_VER
+#include
+typedef UINT32 uint32_t;
+#else
+#include
+#endif
+
+#define CAMELLIA_ENCRYPT 1
+#define CAMELLIA_DECRYPT 0
+
+#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */
+#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */
+
+#if !defined(POLARSSL_CAMELLIA_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief CAMELLIA context structure
+ */
+typedef struct
+{
+ int nr; /*!< number of rounds */
+ uint32_t rk[68]; /*!< CAMELLIA round keys */
+}
+camellia_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief CAMELLIA key schedule (encryption)
+ *
+ * \param ctx CAMELLIA context to be initialized
+ * \param key encryption key
+ * \param keysize must be 128, 192 or 256
+ *
+ * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH
+ */
+int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief CAMELLIA key schedule (decryption)
+ *
+ * \param ctx CAMELLIA context to be initialized
+ * \param key decryption key
+ * \param keysize must be 128, 192 or 256
+ *
+ * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH
+ */
+int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief CAMELLIA-ECB block encryption/decryption
+ *
+ * \param ctx CAMELLIA context
+ * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT
+ * \param input 16-byte input block
+ * \param output 16-byte output block
+ *
+ * \return 0 if successful
+ */
+int camellia_crypt_ecb( camellia_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+/**
+ * \brief CAMELLIA-CBC buffer encryption/decryption
+ * Length should be a multiple of the block
+ * size (16 bytes)
+ *
+ * \param ctx CAMELLIA context
+ * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ */
+int camellia_crypt_cbc( camellia_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief CAMELLIA-CFB128 buffer encryption/decryption
+ *
+ * Note: Due to the nature of CFB you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * camellia_setkey_enc() for both CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT.
+ *
+ * \param ctx CAMELLIA context
+ * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT
+ * \param length length of the input data
+ * \param iv_off offset in IV (updated after use)
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ */
+int camellia_crypt_cfb128( camellia_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief CAMELLIA-CTR buffer encryption/decryption
+ *
+ * Warning: You have to keep the maximum use of your counter in mind!
+ *
+ * Note: Due to the nature of CTR you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * camellia_setkey_enc() for both CAMELLIA_ENCRYPT and CAMELLIA_DECRYPT.
+ *
+ * \param length The length of the data
+ * \param nc_off The offset in the current stream_block (for resuming
+ * within current cipher stream). The offset pointer to
+ * should be 0 at the start of a stream.
+ * \param nonce_counter The 128-bit nonce and counter.
+ * \param stream_block The saved stream-block for resuming. Is overwritten
+ * by the function.
+ * \param input The input data stream
+ * \param output The output data stream
+ *
+ * \return 0 if successful
+ */
+int camellia_crypt_ctr( camellia_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* POLARSSL_CAMELLIA_ALT */
+#include "polarssl/camellia_alt.h"
+#endif /* POLARSSL_CAMELLIA_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int camellia_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* camellia.h */
diff --git a/polarssl/certs.c b/polarssl/certs.c
new file mode 100644
index 0000000..e2d07f7
--- /dev/null
+++ b/polarssl/certs.c
@@ -0,0 +1,196 @@
+/*
+ * X.509 test certificates
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_CERTS_C)
+
+const char test_ca_crt[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
+"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
+"MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n"
+"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n"
+"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n"
+"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n"
+"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n"
+"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n"
+"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n"
+"gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH\r\n"
+"/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV\r\n"
+"BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz\r\n"
+"dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ\r\n"
+"SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H\r\n"
+"DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF\r\n"
+"pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf\r\n"
+"m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n"
+"7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_ca_key[] =
+"-----BEGIN RSA PRIVATE KEY-----\r\n"
+"Proc-Type: 4,ENCRYPTED\r\n"
+"DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n"
+"\r\n"
+"9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n"
+"7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n"
+"Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n"
+"PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n"
+"GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n"
+"gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n"
+"QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n"
+"PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n"
+"vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n"
+"WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n"
+"JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n"
+"KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n"
+"Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n"
+"9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n"
+"iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n"
+"tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n"
+"P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n"
+"1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n"
+"nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n"
+"X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n"
+"rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n"
+"L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n"
+"I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n"
+"wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n"
+"P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n"
+"-----END RSA PRIVATE KEY-----\r\n";
+
+const char test_ca_pwd[] = "PolarSSLTest";
+
+const char test_srv_crt[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIDPzCCAiegAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
+"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
+"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIFNlcnZlciAxMIIBIjAN\r\n"
+"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/\r\n"
+"uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFD\r\n"
+"d185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVf\r\n"
+"CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr\r\n"
+"lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w\r\n"
+"bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB\r\n"
+"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQfdNY/KcF0dEU7BRIsPai9Q1kCpjAf\r\n"
+"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n"
+"AQEAvc+WwZUemsJu2IiI2Cp6liA+UAvIx98dQe3kZs2zAoF9VwQbXcYzWQ/BILkj\r\n"
+"NImKbPL9x0g2jIDn4ZvGYFywMwIO/d++YbwYiQw42/v7RiMy94zBPnzeHi86dy/0\r\n"
+"jpOOJUx3IXRsGLdyjb/1T11klcFqGnARiK+8VYolMPP6afKvLXX7K4kiUpsFQhUp\r\n"
+"E5VeM5pV1Mci2ETOJau2cO40FJvI/C9W/wR+GAArMaw2fxG77E3laaa0LAOlexM6\r\n"
+"A4KOb5f5cGTM5Ih6tEF5FVq3/9vzNIYMa1FqzacBLZF8zSHYLEimXBdzjBoN4qDU\r\n"
+"/WzRyYRBRjAI49mzHX6raleqnw==\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_srv_key[] =
+"-----BEGIN RSA PRIVATE KEY-----\r\n"
+"MIIEogIBAAKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/uOhFkNvuiBZS0/FDUEeW\r\n"
+"Ellkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFDd185fAkER4KwVzlw7aPs\r\n"
+"FRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVfCrFTxjB+FTms+Vruf5Ke\r\n"
+"pgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTrlZvc/kFeF6babFtpzAK6\r\n"
+"FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9wbp7OvViJ4lNZnm5akmXi\r\n"
+"iD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQABAoIBABaJ9eiRQq4Ypv+w\r\n"
+"UTcVpLC0oTueWzcpor1i1zjG4Vzqe/Ok2FqyGToGKMlFK7Hwwa+LEyeJ3xyV5yd4\r\n"
+"v1Mw9bDZFdJC1eCBjoUAHtX6k9HOE0Vd6woVQ4Vi6OPI1g7B5Mnr/58rNrnN6TMs\r\n"
+"x58NF6euecwTU811QJrZtLbX7j2Cr28yB2Vs8qyYlHwVw5jbDOv43D7vU5gmlIDN\r\n"
+"0JQRuWAnOuPzZNoJr4SfJKqHNGxYYY6pHZ1s0dOTLIDb/B8KQWapA2kRmZyid2EH\r\n"
+"nwzgLbAsHJCf+bQnhXjXuxtUsrcIL8noZLazlOMxwNEammglVWW23Ud/QRnFgJg5\r\n"
+"UgcAcRECgYEA19uYetht5qmwdJ+12oC6zeO+vXLcyD9gon23T5J6w2YThld7/OW0\r\n"
+"oArQJGgkAdaq0pcTyOIjtTQVMFygdVmCEJmxh/3RutPcTeydqW9fphKDMej32J8e\r\n"
+"GniGmNGiclbcfNOS8E5TGp445yZb9P1+7AHng16bGg3Ykj5EA4G+HCcCgYEAyHAl\r\n"
+"//ekk8YjQElm+8izLtFkymIK0aCtEe9C/RIRhFYBeFaotC5dStNhBOncn4ovMAPD\r\n"
+"lX/92yDi9OP8PPLN3a4B9XpW3k/SS5GrbT5cwOivBHNllZSmu/2qz5WPGcjVCOrB\r\n"
+"LYl3YWr2h3EGKICT03kEoTkiDBvCeOpW7cCGl2cCgYBD5whoXHz1+ptPlI4YVjZt\r\n"
+"Xh86aU+ajpVPiEyJ84I6xXmO4SZXv8q6LaycR0ZMbcL+zBelMb4Z2nBv7jNrtuR7\r\n"
+"ZF28cdPv+YVr3esaybZE/73VjXup4SQPH6r3l7qKTVi+y6+FeJ4b2Xn8/MwgnT23\r\n"
+"8EFrye7wmzpthrjOgZnUMQKBgE9Lhsz/5J0Nis6Y+2Pqn3CLKEukg9Ewtqdct2y0\r\n"
+"5Dcta0F3TyCRIxlCDKTL/BslqMtfAdY4H268UO0+8IAQMn9boqzBrHIgs/pvc5kx\r\n"
+"TbKHmw2wtWR6vYersBKVgVpbCGSRssDYHGFu1n74qM4HJ/RGcR1zI9QUe1gopSFD\r\n"
+"xDtLAoGAVAdWvrqDwgoL2hHW3scGpxdE/ygJDOwHnf+1B9goKAOP5lf2FJaiAxf3\r\n"
+"ectoPOgZbCmm/iiDmigu703ld3O+VoCLDD4qx3R+KyALL78gtVJYzSRiKhzgCZ3g\r\n"
+"mKsIVRBq4IfwiwyMNG2BYZQAwbSDjjPtn/kPBduPzPj7eriByhI=\r\n"
+"-----END RSA PRIVATE KEY-----\r\n";
+
+const char test_cli_crt[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
+"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
+"MTEwMjEyMTQ0NDA3WhcNMjEwMjEyMTQ0NDA3WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n"
+"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n"
+"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n"
+"1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n"
+"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n"
+"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n"
+"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n"
+"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n"
+"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n"
+"AQEAAn86isAM8X+mVwJqeItt6E9slhEQbAofyk+diH1Lh8Y9iLlWQSKbw/UXYjx5\r\n"
+"LLPZcniovxIcARC/BjyZR9g3UwTHNGNm+rwrqa15viuNOFBchykX/Orsk02EH7NR\r\n"
+"Alw5WLPorYjED6cdVQgBl9ot93HdJogRiXCxErM7NC8/eP511mjq+uLDjLKH8ZPQ\r\n"
+"8I4ekHJnroLsDkIwXKGIsvIBHQy2ac/NwHLCQOK6mfum1pRx52V4Utu5dLLjD5bM\r\n"
+"xOBC7KU4xZKuMXXZM6/93Yb51K/J4ahf1TxJlTWXtnzDr9saEYdNy2SKY/6ZiDNH\r\n"
+"D+stpAKiQLAWaAusIWKYEyw9MQ==\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_cli_key[] =
+"-----BEGIN RSA PRIVATE KEY-----\r\n"
+"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n"
+"B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n"
+"bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n"
+"Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n"
+"7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n"
+"dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n"
+"yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n"
+"4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n"
+"ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n"
+"zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n"
+"l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n"
+"DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n"
+"VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n"
+"Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n"
+"wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n"
+"c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n"
+"33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n"
+"ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n"
+"BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n"
+"KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n"
+"UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n"
+"7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n"
+"gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n"
+"bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n"
+"8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n"
+"-----END RSA PRIVATE KEY-----\r\n";
+
+const char test_dhm_params[] =
+"-----BEGIN DH PARAMETERS-----\r\n"
+"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
+"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
+"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
+"-----END DH PARAMETERS-----\r\n";
+
+#endif
diff --git a/polarssl/certs.h b/polarssl/certs.h
new file mode 100644
index 0000000..5399e32
--- /dev/null
+++ b/polarssl/certs.h
@@ -0,0 +1,47 @@
+/**
+ * \file certs.h
+ *
+ * \brief Sample certificates and DHM parameters for testing
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CERTS_H
+#define POLARSSL_CERTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char test_ca_crt[];
+extern const char test_ca_key[];
+extern const char test_ca_pwd[];
+extern const char test_srv_crt[];
+extern const char test_srv_key[];
+extern const char test_cli_crt[];
+extern const char test_cli_key[];
+extern const char test_dhm_params[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* certs.h */
diff --git a/polarssl/cipher.c b/polarssl/cipher.c
new file mode 100644
index 0000000..f20cc73
--- /dev/null
+++ b/polarssl/cipher.c
@@ -0,0 +1,601 @@
+/**
+ * \file cipher.c
+ *
+ * \brief Generic cipher wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_CIPHER_C)
+
+#include "polarssl/cipher.h"
+#include "polarssl/cipher_wrap.h"
+
+#include
+
+#if defined _MSC_VER && !defined strcasecmp
+#define strcasecmp _stricmp
+#endif
+
+static const int supported_ciphers[] = {
+
+#if defined(POLARSSL_AES_C)
+ POLARSSL_CIPHER_AES_128_CBC,
+ POLARSSL_CIPHER_AES_192_CBC,
+ POLARSSL_CIPHER_AES_256_CBC,
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ POLARSSL_CIPHER_AES_128_CFB128,
+ POLARSSL_CIPHER_AES_192_CFB128,
+ POLARSSL_CIPHER_AES_256_CFB128,
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ POLARSSL_CIPHER_AES_128_CTR,
+ POLARSSL_CIPHER_AES_192_CTR,
+ POLARSSL_CIPHER_AES_256_CTR,
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#endif /* defined(POLARSSL_AES_C) */
+
+#if defined(POLARSSL_CAMELLIA_C)
+ POLARSSL_CIPHER_CAMELLIA_128_CBC,
+ POLARSSL_CIPHER_CAMELLIA_192_CBC,
+ POLARSSL_CIPHER_CAMELLIA_256_CBC,
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ POLARSSL_CIPHER_CAMELLIA_128_CFB128,
+ POLARSSL_CIPHER_CAMELLIA_192_CFB128,
+ POLARSSL_CIPHER_CAMELLIA_256_CFB128,
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ POLARSSL_CIPHER_CAMELLIA_128_CTR,
+ POLARSSL_CIPHER_CAMELLIA_192_CTR,
+ POLARSSL_CIPHER_CAMELLIA_256_CTR,
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#endif /* defined(POLARSSL_CAMELLIA_C) */
+
+#if defined(POLARSSL_DES_C)
+ POLARSSL_CIPHER_DES_CBC,
+ POLARSSL_CIPHER_DES_EDE_CBC,
+ POLARSSL_CIPHER_DES_EDE3_CBC,
+#endif /* defined(POLARSSL_DES_C) */
+
+#if defined(POLARSSL_BLOWFISH_C)
+ POLARSSL_CIPHER_BLOWFISH_CBC,
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ POLARSSL_CIPHER_BLOWFISH_CFB64,
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ POLARSSL_CIPHER_BLOWFISH_CTR,
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#endif /* defined(POLARSSL_BLOWFISH_C) */
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ POLARSSL_CIPHER_NULL,
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+ 0
+};
+
+const int *cipher_list( void )
+{
+ return supported_ciphers;
+}
+
+const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type )
+{
+ /* Find static cipher information */
+ switch ( cipher_type )
+ {
+#if defined(POLARSSL_AES_C)
+ case POLARSSL_CIPHER_AES_128_CBC:
+ return &aes_128_cbc_info;
+ case POLARSSL_CIPHER_AES_192_CBC:
+ return &aes_192_cbc_info;
+ case POLARSSL_CIPHER_AES_256_CBC:
+ return &aes_256_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ case POLARSSL_CIPHER_AES_128_CFB128:
+ return &aes_128_cfb128_info;
+ case POLARSSL_CIPHER_AES_192_CFB128:
+ return &aes_192_cfb128_info;
+ case POLARSSL_CIPHER_AES_256_CFB128:
+ return &aes_256_cfb128_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ case POLARSSL_CIPHER_AES_128_CTR:
+ return &aes_128_ctr_info;
+ case POLARSSL_CIPHER_AES_192_CTR:
+ return &aes_192_ctr_info;
+ case POLARSSL_CIPHER_AES_256_CTR:
+ return &aes_256_ctr_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+ case POLARSSL_CIPHER_CAMELLIA_128_CBC:
+ return &camellia_128_cbc_info;
+ case POLARSSL_CIPHER_CAMELLIA_192_CBC:
+ return &camellia_192_cbc_info;
+ case POLARSSL_CIPHER_CAMELLIA_256_CBC:
+ return &camellia_256_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ case POLARSSL_CIPHER_CAMELLIA_128_CFB128:
+ return &camellia_128_cfb128_info;
+ case POLARSSL_CIPHER_CAMELLIA_192_CFB128:
+ return &camellia_192_cfb128_info;
+ case POLARSSL_CIPHER_CAMELLIA_256_CFB128:
+ return &camellia_256_cfb128_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ case POLARSSL_CIPHER_CAMELLIA_128_CTR:
+ return &camellia_128_ctr_info;
+ case POLARSSL_CIPHER_CAMELLIA_192_CTR:
+ return &camellia_192_ctr_info;
+ case POLARSSL_CIPHER_CAMELLIA_256_CTR:
+ return &camellia_256_ctr_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#endif
+
+#if defined(POLARSSL_DES_C)
+ case POLARSSL_CIPHER_DES_CBC:
+ return &des_cbc_info;
+ case POLARSSL_CIPHER_DES_EDE_CBC:
+ return &des_ede_cbc_info;
+ case POLARSSL_CIPHER_DES_EDE3_CBC:
+ return &des_ede3_cbc_info;
+#endif
+
+#if defined(POLARSSL_BLOWFISH_C)
+ case POLARSSL_CIPHER_BLOWFISH_CBC:
+ return &blowfish_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ case POLARSSL_CIPHER_BLOWFISH_CFB64:
+ return &blowfish_cfb64_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ case POLARSSL_CIPHER_BLOWFISH_CTR:
+ return &blowfish_ctr_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#endif
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ case POLARSSL_CIPHER_NULL:
+ return &null_cipher_info;
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+ default:
+ return NULL;
+ }
+}
+
+const cipher_info_t *cipher_info_from_string( const char *cipher_name )
+{
+ if( NULL == cipher_name )
+ return NULL;
+
+ /* Get the appropriate cipher information */
+#if defined(POLARSSL_CAMELLIA_C)
+ if( !strcasecmp( "CAMELLIA-128-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CBC );
+ if( !strcasecmp( "CAMELLIA-192-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CBC );
+ if( !strcasecmp( "CAMELLIA-256-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CBC );
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ if( !strcasecmp( "CAMELLIA-128-CFB128", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CFB128 );
+ if( !strcasecmp( "CAMELLIA-192-CFB128", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CFB128 );
+ if( !strcasecmp( "CAMELLIA-256-CFB128", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CFB128 );
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ if( !strcasecmp( "CAMELLIA-128-CTR", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CTR );
+ if( !strcasecmp( "CAMELLIA-192-CTR", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CTR );
+ if( !strcasecmp( "CAMELLIA-256-CTR", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CTR );
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+#endif
+
+#if defined(POLARSSL_AES_C)
+ if( !strcasecmp( "AES-128-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CBC );
+ if( !strcasecmp( "AES-192-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CBC );
+ if( !strcasecmp( "AES-256-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CBC );
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ if( !strcasecmp( "AES-128-CFB128", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CFB128 );
+ if( !strcasecmp( "AES-192-CFB128", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CFB128 );
+ if( !strcasecmp( "AES-256-CFB128", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CFB128 );
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ if( !strcasecmp( "AES-128-CTR", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CTR );
+ if( !strcasecmp( "AES-192-CTR", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CTR );
+ if( !strcasecmp( "AES-256-CTR", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CTR );
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+#endif
+
+#if defined(POLARSSL_DES_C)
+ if( !strcasecmp( "DES-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_DES_CBC );
+ if( !strcasecmp( "DES-EDE-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_DES_EDE_CBC );
+ if( !strcasecmp( "DES-EDE3-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_DES_EDE3_CBC );
+#endif
+
+#if defined(POLARSSL_BLOWFISH_C)
+ if( !strcasecmp( "BLOWFISH-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_BLOWFISH_CBC );
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ if( !strcasecmp( "BLOWFISH-CFB64", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_BLOWFISH_CFB64 );
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ if( !strcasecmp( "BLOWFISH-CTR", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_BLOWFISH_CTR );
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+#endif
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ if( !strcasecmp( "NULL", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_NULL );
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+ return NULL;
+}
+
+int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info )
+{
+ if( NULL == cipher_info || NULL == ctx )
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+ memset( ctx, 0, sizeof( cipher_context_t ) );
+
+ if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )
+ return POLARSSL_ERR_CIPHER_ALLOC_FAILED;
+
+ ctx->cipher_info = cipher_info;
+
+ return 0;
+}
+
+int cipher_free_ctx( cipher_context_t *ctx )
+{
+ if( ctx == NULL || ctx->cipher_info == NULL )
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+ ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
+
+ return 0;
+}
+
+int cipher_setkey( cipher_context_t *ctx, const unsigned char *key,
+ int key_length, const operation_t operation )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+ ctx->key_length = key_length;
+ ctx->operation = operation;
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ if( ctx->cipher_info->mode == POLARSSL_MODE_NULL )
+ return 0;
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+ /*
+ * For CFB and CTR mode always use the encryption key schedule
+ */
+ if( POLARSSL_ENCRYPT == operation ||
+ POLARSSL_MODE_CFB == ctx->cipher_info->mode ||
+ POLARSSL_MODE_CTR == ctx->cipher_info->mode )
+ {
+ return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
+ ctx->key_length );
+ }
+
+ if( POLARSSL_DECRYPT == operation )
+ return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
+ ctx->key_length );
+
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+}
+
+int cipher_reset( cipher_context_t *ctx, const unsigned char *iv )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+ ctx->unprocessed_len = 0;
+
+ memcpy( ctx->iv, iv, cipher_get_iv_size( ctx ) );
+
+ return 0;
+}
+
+int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen )
+{
+ int ret;
+ size_t copy_len = 0;
+
+ if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ||
+ input == output )
+ {
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+ }
+
+ *olen = 0;
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ if( ctx->cipher_info->mode == POLARSSL_MODE_NULL )
+ {
+ memcpy( output, input, ilen );
+ *olen = ilen;
+ return 0;
+ }
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+ if( ctx->cipher_info->mode == POLARSSL_MODE_CBC )
+ {
+ /*
+ * If there is not enough data for a full block, cache it.
+ */
+ if( ( ctx->operation == POLARSSL_DECRYPT &&
+ ilen + ctx->unprocessed_len <= cipher_get_block_size( ctx ) ) ||
+ ( ctx->operation == POLARSSL_ENCRYPT &&
+ ilen + ctx->unprocessed_len < cipher_get_block_size( ctx ) ) )
+ {
+ memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
+ ilen );
+
+ ctx->unprocessed_len += ilen;
+ return 0;
+ }
+
+ /*
+ * Process cached data first
+ */
+ if( ctx->unprocessed_len != 0 )
+ {
+ copy_len = cipher_get_block_size( ctx ) - ctx->unprocessed_len;
+
+ memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
+ copy_len );
+
+ if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+ ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
+ ctx->unprocessed_data, output ) ) )
+ {
+ return ret;
+ }
+
+ *olen += cipher_get_block_size( ctx );
+ output += cipher_get_block_size( ctx );
+ ctx->unprocessed_len = 0;
+
+ input += copy_len;
+ ilen -= copy_len;
+ }
+
+ /*
+ * Cache final, incomplete block
+ */
+ if( 0 != ilen )
+ {
+ copy_len = ilen % cipher_get_block_size( ctx );
+ if( copy_len == 0 && ctx->operation == POLARSSL_DECRYPT )
+ copy_len = cipher_get_block_size(ctx);
+
+ memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
+ copy_len );
+
+ ctx->unprocessed_len += copy_len;
+ ilen -= copy_len;
+ }
+
+ /*
+ * Process remaining full blocks
+ */
+ if( ilen )
+ {
+ if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+ ctx->operation, ilen, ctx->iv, input, output ) ) )
+ {
+ return ret;
+ }
+ *olen += ilen;
+ }
+
+ return 0;
+ }
+
+ if( ctx->cipher_info->mode == POLARSSL_MODE_CFB )
+ {
+ if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx,
+ ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
+ input, output ) ) )
+ {
+ return ret;
+ }
+
+ *olen = ilen;
+
+ return 0;
+ }
+
+ if( ctx->cipher_info->mode == POLARSSL_MODE_CTR )
+ {
+ if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
+ ilen, &ctx->unprocessed_len, ctx->iv,
+ ctx->unprocessed_data, input, output ) ) )
+ {
+ return ret;
+ }
+
+ *olen = ilen;
+
+ return 0;
+ }
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+static void add_pkcs_padding( unsigned char *output, size_t output_len,
+ size_t data_len )
+{
+ size_t padding_len = output_len - data_len;
+ unsigned char i = 0;
+
+ for( i = 0; i < padding_len; i++ )
+ output[data_len + i] = (unsigned char) padding_len;
+}
+
+static int get_pkcs_padding( unsigned char *input, unsigned int input_len,
+ size_t *data_len)
+{
+ unsigned int i, padding_len = 0;
+
+ if( NULL == input || NULL == data_len )
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+ padding_len = input[input_len - 1];
+
+ if( padding_len > input_len )
+ return POLARSSL_ERR_CIPHER_INVALID_PADDING;
+
+ for( i = input_len - padding_len; i < input_len; i++ )
+ if( input[i] != padding_len )
+ return POLARSSL_ERR_CIPHER_INVALID_PADDING;
+
+ *data_len = input_len - padding_len;
+
+ return 0;
+}
+
+int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen)
+{
+ int ret = 0;
+
+ if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+ *olen = 0;
+
+ if( POLARSSL_MODE_CFB == ctx->cipher_info->mode ||
+ POLARSSL_MODE_CTR == ctx->cipher_info->mode ||
+ POLARSSL_MODE_NULL == ctx->cipher_info->mode )
+ {
+ return 0;
+ }
+
+ if( POLARSSL_MODE_CBC == ctx->cipher_info->mode )
+ {
+ if( POLARSSL_ENCRYPT == ctx->operation )
+ {
+ add_pkcs_padding( ctx->unprocessed_data, cipher_get_iv_size( ctx ),
+ ctx->unprocessed_len );
+ }
+ else if ( cipher_get_block_size( ctx ) != ctx->unprocessed_len )
+ {
+ /* For decrypt operations, expect a full block */
+ return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
+ }
+
+ /* cipher block */
+ if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+ ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
+ ctx->unprocessed_data, output ) ) )
+ {
+ return ret;
+ }
+
+ /* Set output size for decryption */
+ if( POLARSSL_DECRYPT == ctx->operation )
+ return get_pkcs_padding( output, cipher_get_block_size( ctx ), olen );
+
+ /* Set output size for encryption */
+ *olen = cipher_get_block_size( ctx );
+ return 0;
+ }
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include
+
+#define ASSERT(x) if (!(x)) { \
+ printf( "failed with %i at %s\n", value, (#x) ); \
+ return( 1 ); \
+}
+/*
+ * Checkup routine
+ */
+
+int cipher_self_test( int verbose )
+{
+ ((void) verbose);
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/cipher.h b/polarssl/cipher.h
new file mode 100644
index 0000000..8224128
--- /dev/null
+++ b/polarssl/cipher.h
@@ -0,0 +1,463 @@
+/**
+ * \file cipher.h
+ *
+ * \brief Generic cipher wrapper.
+ *
+ * \author Adriaan de Jong
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef POLARSSL_CIPHER_H
+#define POLARSSL_CIPHER_H
+
+#include
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */
+#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */
+#define POLARSSL_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */
+#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */
+
+typedef enum {
+ POLARSSL_CIPHER_ID_NONE = 0,
+ POLARSSL_CIPHER_ID_NULL,
+ POLARSSL_CIPHER_ID_AES,
+ POLARSSL_CIPHER_ID_DES,
+ POLARSSL_CIPHER_ID_3DES,
+ POLARSSL_CIPHER_ID_CAMELLIA,
+ POLARSSL_CIPHER_ID_BLOWFISH,
+} cipher_id_t;
+
+typedef enum {
+ POLARSSL_CIPHER_NONE = 0,
+ POLARSSL_CIPHER_NULL,
+ POLARSSL_CIPHER_AES_128_CBC,
+ POLARSSL_CIPHER_AES_192_CBC,
+ POLARSSL_CIPHER_AES_256_CBC,
+ POLARSSL_CIPHER_AES_128_CFB128,
+ POLARSSL_CIPHER_AES_192_CFB128,
+ POLARSSL_CIPHER_AES_256_CFB128,
+ POLARSSL_CIPHER_AES_128_CTR,
+ POLARSSL_CIPHER_AES_192_CTR,
+ POLARSSL_CIPHER_AES_256_CTR,
+ POLARSSL_CIPHER_CAMELLIA_128_CBC,
+ POLARSSL_CIPHER_CAMELLIA_192_CBC,
+ POLARSSL_CIPHER_CAMELLIA_256_CBC,
+ POLARSSL_CIPHER_CAMELLIA_128_CFB128,
+ POLARSSL_CIPHER_CAMELLIA_192_CFB128,
+ POLARSSL_CIPHER_CAMELLIA_256_CFB128,
+ POLARSSL_CIPHER_CAMELLIA_128_CTR,
+ POLARSSL_CIPHER_CAMELLIA_192_CTR,
+ POLARSSL_CIPHER_CAMELLIA_256_CTR,
+ POLARSSL_CIPHER_DES_CBC,
+ POLARSSL_CIPHER_DES_EDE_CBC,
+ POLARSSL_CIPHER_DES_EDE3_CBC,
+ POLARSSL_CIPHER_BLOWFISH_CBC,
+ POLARSSL_CIPHER_BLOWFISH_CFB64,
+ POLARSSL_CIPHER_BLOWFISH_CTR,
+} cipher_type_t;
+
+typedef enum {
+ POLARSSL_MODE_NONE = 0,
+ POLARSSL_MODE_NULL,
+ POLARSSL_MODE_CBC,
+ POLARSSL_MODE_CFB,
+ POLARSSL_MODE_OFB,
+ POLARSSL_MODE_CTR,
+} cipher_mode_t;
+
+typedef enum {
+ POLARSSL_OPERATION_NONE = -1,
+ POLARSSL_DECRYPT = 0,
+ POLARSSL_ENCRYPT,
+} operation_t;
+
+enum {
+ /** Undefined key length */
+ POLARSSL_KEY_LENGTH_NONE = 0,
+ /** Key length, in bits (including parity), for DES keys */
+ POLARSSL_KEY_LENGTH_DES = 64,
+ /** Key length, in bits (including parity), for DES in two key EDE */
+ POLARSSL_KEY_LENGTH_DES_EDE = 128,
+ /** Key length, in bits (including parity), for DES in three-key EDE */
+ POLARSSL_KEY_LENGTH_DES_EDE3 = 192,
+ /** Maximum length of any IV, in bytes */
+ POLARSSL_MAX_IV_LENGTH = 16,
+};
+
+/**
+ * Base cipher information. The non-mode specific functions and values.
+ */
+typedef struct {
+
+ /** Base Cipher type (e.g. POLARSSL_CIPHER_ID_AES) */
+ cipher_id_t cipher;
+
+ /** Encrypt using CBC */
+ int (*cbc_func)( void *ctx, operation_t mode, size_t length, unsigned char *iv,
+ const unsigned char *input, unsigned char *output );
+
+ /** Encrypt using CFB (Full length) */
+ int (*cfb_func)( void *ctx, operation_t mode, size_t length, size_t *iv_off,
+ unsigned char *iv, const unsigned char *input, unsigned char *output );
+
+ /** Encrypt using CTR */
+ int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter,
+ unsigned char *stream_block, const unsigned char *input, unsigned char *output );
+
+ /** Set key for encryption purposes */
+ int (*setkey_enc_func)( void *ctx, const unsigned char *key, unsigned int key_length);
+
+ /** Set key for decryption purposes */
+ int (*setkey_dec_func)( void *ctx, const unsigned char *key, unsigned int key_length);
+
+ /** Allocate a new context */
+ void * (*ctx_alloc_func)( void );
+
+ /** Free the given context */
+ void (*ctx_free_func)( void *ctx );
+
+} cipher_base_t;
+
+/**
+ * Cipher information. Allows cipher functions to be called in a generic way.
+ */
+typedef struct {
+ /** Full cipher identifier (e.g. POLARSSL_CIPHER_AES_256_CBC) */
+ cipher_type_t type;
+
+ /** Cipher mode (e.g. POLARSSL_MODE_CBC) */
+ cipher_mode_t mode;
+
+ /** Cipher key length, in bits (default length for variable sized ciphers)
+ * (Includes parity bits for ciphers like DES) */
+ unsigned int key_length;
+
+ /** Name of the cipher */
+ const char * name;
+
+ /** IV size, in bytes */
+ unsigned int iv_size;
+
+ /** block size, in bytes */
+ unsigned int block_size;
+
+ /** Base cipher information and functions */
+ const cipher_base_t *base;
+
+} cipher_info_t;
+
+/**
+ * Generic cipher context.
+ */
+typedef struct {
+ /** Information about the associated cipher */
+ const cipher_info_t *cipher_info;
+
+ /** Key length to use */
+ int key_length;
+
+ /** Operation that the context's key has been initialised for */
+ operation_t operation;
+
+ /** Buffer for data that hasn't been encrypted yet */
+ unsigned char unprocessed_data[POLARSSL_MAX_IV_LENGTH];
+
+ /** Number of bytes that still need processing */
+ size_t unprocessed_len;
+
+ /** Current IV or NONCE_COUNTER for CTR-mode */
+ unsigned char iv[POLARSSL_MAX_IV_LENGTH];
+
+ /** Cipher-specific context */
+ void *cipher_ctx;
+} cipher_context_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Returns the list of ciphers supported by the generic cipher module.
+ *
+ * \return a statically allocated array of ciphers, the last entry
+ * is 0.
+ */
+const int *cipher_list( void );
+
+/**
+ * \brief Returns the cipher information structure associated
+ * with the given cipher name.
+ *
+ * \param cipher_name Name of the cipher to search for.
+ *
+ * \return the cipher information structure associated with the
+ * given cipher_name, or NULL if not found.
+ */
+const cipher_info_t *cipher_info_from_string( const char *cipher_name );
+
+/**
+ * \brief Returns the cipher information structure associated
+ * with the given cipher type.
+ *
+ * \param cipher_type Type of the cipher to search for.
+ *
+ * \return the cipher information structure associated with the
+ * given cipher_type, or NULL if not found.
+ */
+const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type );
+
+/**
+ * \brief Initialises and fills the cipher context structure with
+ * the appropriate values.
+ *
+ * \param ctx context to initialise. May not be NULL.
+ * \param cipher_info cipher to use.
+ *
+ * \return \c 0 on success,
+ * \c POLARSSL_ERR_CIPHER_BAD_INPUT_DATA on parameter failure,
+ * \c POLARSSL_ERR_CIPHER_ALLOC_FAILED if allocation of the
+ * cipher-specific context failed.
+ */
+int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info );
+
+/**
+ * \brief Free the cipher-specific context of ctx. Freeing ctx
+ * itself remains the responsibility of the caller.
+ *
+ * \param ctx Free the cipher-specific context
+ *
+ * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ * parameter verification fails.
+ */
+int cipher_free_ctx( cipher_context_t *ctx );
+
+/**
+ * \brief Returns the block size of the given cipher.
+ *
+ * \param ctx cipher's context. Must have been initialised.
+ *
+ * \return size of the cipher's blocks, or 0 if ctx has not been
+ * initialised.
+ */
+static inline unsigned int cipher_get_block_size( const cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return 0;
+
+ return ctx->cipher_info->block_size;
+}
+
+/**
+ * \brief Returns the mode of operation for the cipher.
+ * (e.g. POLARSSL_MODE_CBC)
+ *
+ * \param ctx cipher's context. Must have been initialised.
+ *
+ * \return mode of operation, or POLARSSL_MODE_NONE if ctx
+ * has not been initialised.
+ */
+static inline cipher_mode_t cipher_get_cipher_mode( const cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return POLARSSL_MODE_NONE;
+
+ return ctx->cipher_info->mode;
+}
+
+/**
+ * \brief Returns the size of the cipher's IV.
+ *
+ * \param ctx cipher's context. Must have been initialised.
+ *
+ * \return size of the cipher's IV, or 0 if ctx has not been
+ * initialised.
+ */
+static inline int cipher_get_iv_size( const cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return 0;
+
+ return ctx->cipher_info->iv_size;
+}
+
+/**
+ * \brief Returns the type of the given cipher.
+ *
+ * \param ctx cipher's context. Must have been initialised.
+ *
+ * \return type of the cipher, or POLARSSL_CIPHER_NONE if ctx has
+ * not been initialised.
+ */
+static inline cipher_type_t cipher_get_type( const cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return POLARSSL_CIPHER_NONE;
+
+ return ctx->cipher_info->type;
+}
+
+/**
+ * \brief Returns the name of the given cipher, as a string.
+ *
+ * \param ctx cipher's context. Must have been initialised.
+ *
+ * \return name of the cipher, or NULL if ctx was not initialised.
+ */
+static inline const char *cipher_get_name( const cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return 0;
+
+ return ctx->cipher_info->name;
+}
+
+/**
+ * \brief Returns the key length of the cipher.
+ *
+ * \param ctx cipher's context. Must have been initialised.
+ *
+ * \return cipher's key length, in bits, or
+ * POLARSSL_KEY_LENGTH_NONE if ctx has not been
+ * initialised.
+ */
+static inline int cipher_get_key_size ( const cipher_context_t *ctx )
+{
+ if( NULL == ctx )
+ return POLARSSL_KEY_LENGTH_NONE;
+
+ return ctx->key_length;
+}
+
+/**
+ * \brief Returns the operation of the given cipher.
+ *
+ * \param ctx cipher's context. Must have been initialised.
+ *
+ * \return operation (POLARSSL_ENCRYPT or POLARSSL_DECRYPT),
+ * or POLARSSL_OPERATION_NONE if ctx has not been
+ * initialised.
+ */
+static inline operation_t cipher_get_operation( const cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return POLARSSL_OPERATION_NONE;
+
+ return ctx->operation;
+}
+
+/**
+ * \brief Set the key to use with the given context.
+ *
+ * \param ctx generic cipher context. May not be NULL. Must have been
+ * initialised using cipher_context_from_type or
+ * cipher_context_from_string.
+ * \param key The key to use.
+ * \param key_length key length to use, in bits.
+ * \param operation Operation that the key will be used for, either
+ * POLARSSL_ENCRYPT or POLARSSL_DECRYPT.
+ *
+ * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ * parameter verification fails or a cipher specific
+ * error code.
+ */
+int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, int key_length,
+ const operation_t operation );
+
+/**
+ * \brief Reset the given context, setting the IV to iv
+ *
+ * \param ctx generic cipher context
+ * \param iv IV to use or NONCE_COUNTER in the case of a CTR-mode cipher
+ *
+ * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA
+ * if parameter verification fails.
+ */
+int cipher_reset( cipher_context_t *ctx, const unsigned char *iv );
+
+/**
+ * \brief Generic cipher update function. Encrypts/decrypts
+ * using the given cipher context. Writes as many block
+ * size'd blocks of data as possible to output. Any data
+ * that cannot be written immediately will either be added
+ * to the next block, or flushed when cipher_final is
+ * called.
+ *
+ * \param ctx generic cipher context
+ * \param input buffer holding the input data
+ * \param ilen length of the input data
+ * \param output buffer for the output data. Should be able to hold at
+ * least ilen + block_size. Cannot be the same buffer as
+ * input!
+ * \param olen length of the output data, will be filled with the
+ * actual number of bytes written.
+ *
+ * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ * parameter verification fails,
+ * POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE on an
+ * unsupported mode for a cipher or a cipher specific
+ * error code.
+ */
+int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen );
+
+/**
+ * \brief Generic cipher finalisation function. If data still
+ * needs to be flushed from an incomplete block, data
+ * contained within it will be padded with the size of
+ * the last block, and written to the output buffer.
+ *
+ * \param ctx Generic cipher context
+ * \param output buffer to write data to. Needs block_size data available.
+ * \param olen length of the data written to the output buffer.
+ *
+ * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ * parameter verification fails,
+ * POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption
+ * expected a full block but was not provided one,
+ * POLARSSL_ERR_CIPHER_INVALID_PADDING on invalid padding
+ * while decrypting or a cipher specific error code.
+ */
+int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen);
+
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int cipher_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_MD_H */
diff --git a/polarssl/cipher_wrap.c b/polarssl/cipher_wrap.c
new file mode 100644
index 0000000..9437212
--- /dev/null
+++ b/polarssl/cipher_wrap.c
@@ -0,0 +1,711 @@
+/**
+ * \file md_wrap.c
+ *
+ * \brief Generic cipher wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_CIPHER_C)
+
+#include "polarssl/cipher_wrap.h"
+
+#if defined(POLARSSL_AES_C)
+#include "polarssl/aes.h"
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+#include "polarssl/camellia.h"
+#endif
+
+#if defined(POLARSSL_DES_C)
+#include "polarssl/des.h"
+#endif
+
+#if defined(POLARSSL_BLOWFISH_C)
+#include "polarssl/blowfish.h"
+#endif
+
+#include
+
+#if defined(POLARSSL_AES_C)
+
+int aes_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+ unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ return aes_crypt_cbc( (aes_context *) ctx, operation, length, iv, input, output );
+}
+
+int aes_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
+ size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ return aes_crypt_cfb128( (aes_context *) ctx, operation, length, iv_off, iv, input, output );
+#else
+ ((void) ctx);
+ ((void) operation);
+ ((void) length);
+ ((void) iv_off);
+ ((void) iv);
+ ((void) input);
+ ((void) output);
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int aes_crypt_ctr_wrap( void *ctx, size_t length,
+ size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
+ const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ return aes_crypt_ctr( (aes_context *) ctx, length, nc_off, nonce_counter,
+ stream_block, input, output );
+#else
+ ((void) ctx);
+ ((void) length);
+ ((void) nc_off);
+ ((void) nonce_counter);
+ ((void) stream_block);
+ ((void) input);
+ ((void) output);
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ return aes_setkey_dec( (aes_context *) ctx, key, key_length );
+}
+
+int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ return aes_setkey_enc( (aes_context *) ctx, key, key_length );
+}
+
+static void * aes_ctx_alloc( void )
+{
+ return malloc( sizeof( aes_context ) );
+}
+
+static void aes_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const cipher_base_t aes_info = {
+ POLARSSL_CIPHER_ID_AES,
+ aes_crypt_cbc_wrap,
+ aes_crypt_cfb128_wrap,
+ aes_crypt_ctr_wrap,
+ aes_setkey_enc_wrap,
+ aes_setkey_dec_wrap,
+ aes_ctx_alloc,
+ aes_ctx_free
+};
+
+const cipher_info_t aes_128_cbc_info = {
+ POLARSSL_CIPHER_AES_128_CBC,
+ POLARSSL_MODE_CBC,
+ 128,
+ "AES-128-CBC",
+ 16,
+ 16,
+ &aes_info
+};
+
+const cipher_info_t aes_192_cbc_info = {
+ POLARSSL_CIPHER_AES_192_CBC,
+ POLARSSL_MODE_CBC,
+ 192,
+ "AES-192-CBC",
+ 16,
+ 16,
+ &aes_info
+};
+
+const cipher_info_t aes_256_cbc_info = {
+ POLARSSL_CIPHER_AES_256_CBC,
+ POLARSSL_MODE_CBC,
+ 256,
+ "AES-256-CBC",
+ 16,
+ 16,
+ &aes_info
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+const cipher_info_t aes_128_cfb128_info = {
+ POLARSSL_CIPHER_AES_128_CFB128,
+ POLARSSL_MODE_CFB,
+ 128,
+ "AES-128-CFB128",
+ 16,
+ 16,
+ &aes_info
+};
+
+const cipher_info_t aes_192_cfb128_info = {
+ POLARSSL_CIPHER_AES_192_CFB128,
+ POLARSSL_MODE_CFB,
+ 192,
+ "AES-192-CFB128",
+ 16,
+ 16,
+ &aes_info
+};
+
+const cipher_info_t aes_256_cfb128_info = {
+ POLARSSL_CIPHER_AES_256_CFB128,
+ POLARSSL_MODE_CFB,
+ 256,
+ "AES-256-CFB128",
+ 16,
+ 16,
+ &aes_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+const cipher_info_t aes_128_ctr_info = {
+ POLARSSL_CIPHER_AES_128_CTR,
+ POLARSSL_MODE_CTR,
+ 128,
+ "AES-128-CTR",
+ 16,
+ 16,
+ &aes_info
+};
+
+const cipher_info_t aes_192_ctr_info = {
+ POLARSSL_CIPHER_AES_192_CTR,
+ POLARSSL_MODE_CTR,
+ 192,
+ "AES-192-CTR",
+ 16,
+ 16,
+ &aes_info
+};
+
+const cipher_info_t aes_256_ctr_info = {
+ POLARSSL_CIPHER_AES_256_CTR,
+ POLARSSL_MODE_CTR,
+ 256,
+ "AES-256-CTR",
+ 16,
+ 16,
+ &aes_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+
+int camellia_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+ unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ return camellia_crypt_cbc( (camellia_context *) ctx, operation, length, iv, input, output );
+}
+
+int camellia_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
+ size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ return camellia_crypt_cfb128( (camellia_context *) ctx, operation, length, iv_off, iv, input, output );
+#else
+ ((void) ctx);
+ ((void) operation);
+ ((void) length);
+ ((void) iv_off);
+ ((void) iv);
+ ((void) input);
+ ((void) output);
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int camellia_crypt_ctr_wrap( void *ctx, size_t length,
+ size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
+ const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ return camellia_crypt_ctr( (camellia_context *) ctx, length, nc_off, nonce_counter,
+ stream_block, input, output );
+#else
+ ((void) ctx);
+ ((void) length);
+ ((void) nc_off);
+ ((void) nonce_counter);
+ ((void) stream_block);
+ ((void) input);
+ ((void) output);
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ return camellia_setkey_dec( (camellia_context *) ctx, key, key_length );
+}
+
+int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ return camellia_setkey_enc( (camellia_context *) ctx, key, key_length );
+}
+
+static void * camellia_ctx_alloc( void )
+{
+ return malloc( sizeof( camellia_context ) );
+}
+
+static void camellia_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const cipher_base_t camellia_info = {
+ POLARSSL_CIPHER_ID_CAMELLIA,
+ camellia_crypt_cbc_wrap,
+ camellia_crypt_cfb128_wrap,
+ camellia_crypt_ctr_wrap,
+ camellia_setkey_enc_wrap,
+ camellia_setkey_dec_wrap,
+ camellia_ctx_alloc,
+ camellia_ctx_free
+};
+
+const cipher_info_t camellia_128_cbc_info = {
+ POLARSSL_CIPHER_CAMELLIA_128_CBC,
+ POLARSSL_MODE_CBC,
+ 128,
+ "CAMELLIA-128-CBC",
+ 16,
+ 16,
+ &camellia_info
+};
+
+const cipher_info_t camellia_192_cbc_info = {
+ POLARSSL_CIPHER_CAMELLIA_192_CBC,
+ POLARSSL_MODE_CBC,
+ 192,
+ "CAMELLIA-192-CBC",
+ 16,
+ 16,
+ &camellia_info
+};
+
+const cipher_info_t camellia_256_cbc_info = {
+ POLARSSL_CIPHER_CAMELLIA_256_CBC,
+ POLARSSL_MODE_CBC,
+ 256,
+ "CAMELLIA-256-CBC",
+ 16,
+ 16,
+ &camellia_info
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+const cipher_info_t camellia_128_cfb128_info = {
+ POLARSSL_CIPHER_CAMELLIA_128_CFB128,
+ POLARSSL_MODE_CFB,
+ 128,
+ "CAMELLIA-128-CFB128",
+ 16,
+ 16,
+ &camellia_info
+};
+
+const cipher_info_t camellia_192_cfb128_info = {
+ POLARSSL_CIPHER_CAMELLIA_192_CFB128,
+ POLARSSL_MODE_CFB,
+ 192,
+ "CAMELLIA-192-CFB128",
+ 16,
+ 16,
+ &camellia_info
+};
+
+const cipher_info_t camellia_256_cfb128_info = {
+ POLARSSL_CIPHER_CAMELLIA_256_CFB128,
+ POLARSSL_MODE_CFB,
+ 256,
+ "CAMELLIA-256-CFB128",
+ 16,
+ 16,
+ &camellia_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+const cipher_info_t camellia_128_ctr_info = {
+ POLARSSL_CIPHER_CAMELLIA_128_CTR,
+ POLARSSL_MODE_CTR,
+ 128,
+ "CAMELLIA-128-CTR",
+ 16,
+ 16,
+ &camellia_info
+};
+
+const cipher_info_t camellia_192_ctr_info = {
+ POLARSSL_CIPHER_CAMELLIA_192_CTR,
+ POLARSSL_MODE_CTR,
+ 192,
+ "CAMELLIA-192-CTR",
+ 16,
+ 16,
+ &camellia_info
+};
+
+const cipher_info_t camellia_256_ctr_info = {
+ POLARSSL_CIPHER_CAMELLIA_256_CTR,
+ POLARSSL_MODE_CTR,
+ 256,
+ "CAMELLIA-256-CTR",
+ 16,
+ 16,
+ &camellia_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#endif
+
+#if defined(POLARSSL_DES_C)
+
+int des_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+ unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ return des_crypt_cbc( (des_context *) ctx, operation, length, iv, input, output );
+}
+
+int des3_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+ unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ return des3_crypt_cbc( (des3_context *) ctx, operation, length, iv, input, output );
+}
+
+int des_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
+ size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ ((void) ctx);
+ ((void) operation);
+ ((void) length);
+ ((void) iv_off);
+ ((void) iv);
+ ((void) input);
+ ((void) output);
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+int des_crypt_ctr_wrap( void *ctx, size_t length,
+ size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
+ const unsigned char *input, unsigned char *output )
+{
+ ((void) ctx);
+ ((void) length);
+ ((void) nc_off);
+ ((void) nonce_counter);
+ ((void) stream_block);
+ ((void) input);
+ ((void) output);
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+
+int des_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ ((void) key_length);
+
+ return des_setkey_dec( (des_context *) ctx, key );
+}
+
+int des_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ ((void) key_length);
+
+ return des_setkey_enc( (des_context *) ctx, key );
+}
+
+int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ ((void) key_length);
+
+ return des3_set2key_dec( (des3_context *) ctx, key );
+}
+
+int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ ((void) key_length);
+
+ return des3_set2key_enc( (des3_context *) ctx, key );
+}
+
+int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ ((void) key_length);
+
+ return des3_set3key_dec( (des3_context *) ctx, key );
+}
+
+int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ ((void) key_length);
+
+ return des3_set3key_enc( (des3_context *) ctx, key );
+}
+
+static void * des_ctx_alloc( void )
+{
+ return malloc( sizeof( des_context ) );
+}
+
+static void * des3_ctx_alloc( void )
+{
+ return malloc( sizeof( des3_context ) );
+}
+
+static void des_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const cipher_base_t des_info = {
+ POLARSSL_CIPHER_ID_DES,
+ des_crypt_cbc_wrap,
+ des_crypt_cfb128_wrap,
+ des_crypt_ctr_wrap,
+ des_setkey_enc_wrap,
+ des_setkey_dec_wrap,
+ des_ctx_alloc,
+ des_ctx_free
+};
+
+const cipher_info_t des_cbc_info = {
+ POLARSSL_CIPHER_DES_CBC,
+ POLARSSL_MODE_CBC,
+ POLARSSL_KEY_LENGTH_DES,
+ "DES-CBC",
+ 8,
+ 8,
+ &des_info
+};
+
+const cipher_base_t des_ede_info = {
+ POLARSSL_CIPHER_ID_DES,
+ des3_crypt_cbc_wrap,
+ des_crypt_cfb128_wrap,
+ des_crypt_ctr_wrap,
+ des3_set2key_enc_wrap,
+ des3_set2key_dec_wrap,
+ des3_ctx_alloc,
+ des_ctx_free
+};
+
+const cipher_info_t des_ede_cbc_info = {
+ POLARSSL_CIPHER_DES_EDE_CBC,
+ POLARSSL_MODE_CBC,
+ POLARSSL_KEY_LENGTH_DES_EDE,
+ "DES-EDE-CBC",
+ 8,
+ 8,
+ &des_ede_info
+};
+
+const cipher_base_t des_ede3_info = {
+ POLARSSL_CIPHER_ID_DES,
+ des3_crypt_cbc_wrap,
+ des_crypt_cfb128_wrap,
+ des_crypt_ctr_wrap,
+ des3_set3key_enc_wrap,
+ des3_set3key_dec_wrap,
+ des3_ctx_alloc,
+ des_ctx_free
+};
+
+const cipher_info_t des_ede3_cbc_info = {
+ POLARSSL_CIPHER_DES_EDE3_CBC,
+ POLARSSL_MODE_CBC,
+ POLARSSL_KEY_LENGTH_DES_EDE3,
+ "DES-EDE3-CBC",
+ 8,
+ 8,
+ &des_ede3_info
+};
+#endif
+
+#if defined(POLARSSL_BLOWFISH_C)
+
+int blowfish_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+ unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ return blowfish_crypt_cbc( (blowfish_context *) ctx, operation, length, iv, input, output );
+}
+
+int blowfish_crypt_cfb64_wrap( void *ctx, operation_t operation, size_t length,
+ size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ return blowfish_crypt_cfb64( (blowfish_context *) ctx, operation, length, iv_off, iv, input, output );
+#else
+ ((void) ctx);
+ ((void) operation);
+ ((void) length);
+ ((void) iv_off);
+ ((void) iv);
+ ((void) input);
+ ((void) output);
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int blowfish_crypt_ctr_wrap( void *ctx, size_t length,
+ size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
+ const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ return blowfish_crypt_ctr( (blowfish_context *) ctx, length, nc_off, nonce_counter,
+ stream_block, input, output );
+#else
+ ((void) ctx);
+ ((void) length);
+ ((void) nc_off);
+ ((void) nonce_counter);
+ ((void) stream_block);
+ ((void) input);
+ ((void) output);
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int blowfish_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ return blowfish_setkey( (blowfish_context *) ctx, key, key_length );
+}
+
+int blowfish_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ return blowfish_setkey( (blowfish_context *) ctx, key, key_length );
+}
+
+static void * blowfish_ctx_alloc( void )
+{
+ return malloc( sizeof( blowfish_context ) );
+}
+
+static void blowfish_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const cipher_base_t blowfish_info = {
+ POLARSSL_CIPHER_ID_BLOWFISH,
+ blowfish_crypt_cbc_wrap,
+ blowfish_crypt_cfb64_wrap,
+ blowfish_crypt_ctr_wrap,
+ blowfish_setkey_enc_wrap,
+ blowfish_setkey_dec_wrap,
+ blowfish_ctx_alloc,
+ blowfish_ctx_free
+};
+
+const cipher_info_t blowfish_cbc_info = {
+ POLARSSL_CIPHER_BLOWFISH_CBC,
+ POLARSSL_MODE_CBC,
+ 128,
+ "BLOWFISH-CBC",
+ 8,
+ 8,
+ &blowfish_info
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+const cipher_info_t blowfish_cfb64_info = {
+ POLARSSL_CIPHER_BLOWFISH_CFB64,
+ POLARSSL_MODE_CFB,
+ 128,
+ "BLOWFISH-CFB64",
+ 8,
+ 8,
+ &blowfish_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+const cipher_info_t blowfish_ctr_info = {
+ POLARSSL_CIPHER_BLOWFISH_CTR,
+ POLARSSL_MODE_CTR,
+ 128,
+ "BLOWFISH-CTR",
+ 8,
+ 8,
+ &blowfish_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+#endif /* POLARSSL_BLOWFISH_C */
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+static void * null_ctx_alloc( void )
+{
+ return (void *) 1;
+}
+
+
+static void null_ctx_free( void *ctx )
+{
+ ((void) ctx);
+}
+
+const cipher_base_t null_base_info = {
+ POLARSSL_CIPHER_ID_NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ null_ctx_alloc,
+ null_ctx_free
+};
+
+const cipher_info_t null_cipher_info = {
+ POLARSSL_CIPHER_NULL,
+ POLARSSL_MODE_NULL,
+ 0,
+ "NULL",
+ 1,
+ 1,
+ &null_base_info
+};
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+#endif
diff --git a/polarssl/cipher_wrap.h b/polarssl/cipher_wrap.h
new file mode 100644
index 0000000..2f18eff
--- /dev/null
+++ b/polarssl/cipher_wrap.h
@@ -0,0 +1,107 @@
+/**
+ * \file cipher_wrap.h
+ *
+ * \brief Cipher wrappers.
+ *
+ * \author Adriaan de Jong
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CIPHER_WRAP_H
+#define POLARSSL_CIPHER_WRAP_H
+
+#include "polarssl/config.h"
+#include "polarssl/cipher.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(POLARSSL_AES_C)
+
+extern const cipher_info_t aes_128_cbc_info;
+extern const cipher_info_t aes_192_cbc_info;
+extern const cipher_info_t aes_256_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+extern const cipher_info_t aes_128_cfb128_info;
+extern const cipher_info_t aes_192_cfb128_info;
+extern const cipher_info_t aes_256_cfb128_info;
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+extern const cipher_info_t aes_128_ctr_info;
+extern const cipher_info_t aes_192_ctr_info;
+extern const cipher_info_t aes_256_ctr_info;
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#endif /* defined(POLARSSL_AES_C) */
+
+#if defined(POLARSSL_CAMELLIA_C)
+
+extern const cipher_info_t camellia_128_cbc_info;
+extern const cipher_info_t camellia_192_cbc_info;
+extern const cipher_info_t camellia_256_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+extern const cipher_info_t camellia_128_cfb128_info;
+extern const cipher_info_t camellia_192_cfb128_info;
+extern const cipher_info_t camellia_256_cfb128_info;
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+extern const cipher_info_t camellia_128_ctr_info;
+extern const cipher_info_t camellia_192_ctr_info;
+extern const cipher_info_t camellia_256_ctr_info;
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#endif /* defined(POLARSSL_CAMELLIA_C) */
+
+#if defined(POLARSSL_DES_C)
+
+extern const cipher_info_t des_cbc_info;
+extern const cipher_info_t des_ede_cbc_info;
+extern const cipher_info_t des_ede3_cbc_info;
+
+#endif /* defined(POLARSSL_DES_C) */
+
+#if defined(POLARSSL_BLOWFISH_C)
+extern const cipher_info_t blowfish_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+extern const cipher_info_t blowfish_cfb64_info;
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+extern const cipher_info_t blowfish_ctr_info;
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+#endif /* defined(POLARSSL_BLOWFISH_C) */
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+extern const cipher_info_t null_cipher_info;
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_CIPHER_WRAP_H */
diff --git a/polarssl/config.h b/polarssl/config.h
new file mode 100644
index 0000000..bd1a466
--- /dev/null
+++ b/polarssl/config.h
@@ -0,0 +1,1012 @@
+/**
+ * \file config.h
+ *
+ * \brief Configuration options (set of defines)
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * This set of compile-time options may be used to enable
+ * or disable features selectively, and reduce the global
+ * memory footprint.
+ */
+#ifndef POLARSSL_CONFIG_H
+#define POLARSSL_CONFIG_H
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+/**
+ * \name SECTION: System support
+ *
+ * This section sets system specific settings.
+ * \{
+ */
+
+/**
+ * \def POLARSSL_HAVE_INT8
+ *
+ * The system uses 8-bit wide native integers.
+ *
+ * Uncomment if native integers are 8-bit wide.
+#define POLARSSL_HAVE_INT8
+ */
+
+/**
+ * \def POLARSSL_HAVE_INT16
+ *
+ * The system uses 16-bit wide native integers.
+ *
+ * Uncomment if native integers are 16-bit wide.
+#define POLARSSL_HAVE_INT16
+ */
+
+/**
+ * \def POLARSSL_HAVE_LONGLONG
+ *
+ * The compiler supports the 'long long' type.
+ * (Only used on 32-bit platforms)
+ */
+#define POLARSSL_HAVE_LONGLONG
+
+/**
+ * \def POLARSSL_HAVE_ASM
+ *
+ * The compiler has support for asm()
+ *
+ * Uncomment to enable the use of assembly code.
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ * library/timing.c
+ * library/padlock.c
+ * include/polarssl/bn_mul.h
+ *
+ */
+#define POLARSSL_HAVE_ASM
+
+/**
+ * \def POLARSSL_HAVE_SSE2
+ *
+ * CPU supports SSE2 instruction set.
+ *
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ *
+#define POLARSSL_HAVE_SSE2
+ */
+/* \} name */
+
+/**
+ * \name SECTION: PolarSSL feature support
+ *
+ * This section sets support for features that are or are not needed
+ * within the modules that are enabled.
+ * \{
+ */
+
+/**
+ * \def POLARSSL_XXX_ALT
+ *
+ * Uncomment a macro to let PolarSSL use your alternate core implementation of
+ * a symmetric or hash algorithm (e.g. platform specific assembly optimized
+ * implementations). Keep in mind that the function prototypes should remain
+ * the same.
+ *
+ * Example: In case you uncomment POLARSSL_AES_ALT, PolarSSL will no longer
+ * provide the "struct aes_context" definition and omit the base function
+ * declarations and implementations. "aes_alt.h" will be included from
+ * "aes.h" to include the new function definitions.
+ *
+ * Uncomment a macro to enable alternate implementation for core algorithm
+ * functions
+#define POLARSSL_AES_ALT
+#define POLARSSL_ARC4_ALT
+#define POLARSSL_BLOWFISH_ALT
+#define POLARSSL_CAMELLIA_ALT
+#define POLARSSL_DES_ALT
+#define POLARSSL_XTEA_ALT
+#define POLARSSL_MD2_ALT
+#define POLARSSL_MD4_ALT
+#define POLARSSL_MD5_ALT
+#define POLARSSL_SHA1_ALT
+#define POLARSSL_SHA2_ALT
+#define POLARSSL_SHA4_ALT
+ */
+
+/**
+ * \def POLARSSL_AES_ROM_TABLES
+ *
+ * Store the AES tables in ROM.
+ *
+ * Uncomment this macro to store the AES tables in ROM.
+ *
+#define POLARSSL_AES_ROM_TABLES
+ */
+
+/**
+ * \def POLARSSL_CIPHER_MODE_CFB
+ *
+ * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
+ */
+#define POLARSSL_CIPHER_MODE_CFB
+
+/**
+ * \def POLARSSL_CIPHER_MODE_CTR
+ *
+ * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
+ */
+#define POLARSSL_CIPHER_MODE_CTR
+
+/**
+ * \def POLARSSL_CIPHER_NULL_CIPHER
+ *
+ * Enable NULL cipher.
+ * Warning: Only do so when you know what you are doing. This allows for
+ * encryption or channels without any security!
+ *
+ * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable
+ * the following ciphersuites:
+ * TLS_RSA_WITH_NULL_MD5
+ * TLS_RSA_WITH_NULL_SHA
+ * TLS_RSA_WITH_NULL_SHA256
+ *
+ * Uncomment this macro to enable the NULL cipher and ciphersuites
+#define POLARSSL_CIPHER_NULL_CIPHER
+ */
+
+/**
+ * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES
+ *
+ * Enable weak ciphersuites in SSL / TLS
+ * Warning: Only do so when you know what you are doing. This allows for
+ * channels with virtually no security at all!
+ *
+ * This enables the following ciphersuites:
+ * TLS_RSA_WITH_DES_CBC_SHA
+ * TLS_DHE_RSA_WITH_DES_CBC_SHA
+ *
+ * Uncomment this macro to enable weak ciphersuites
+#define POLARSSL_ENABLE_WEAK_CIPHERSUITES
+ */
+
+/**
+ * \def POLARSSL_ERROR_STRERROR_DUMMY
+ *
+ * Enable a dummy error function to make use of error_strerror() in
+ * third party libraries easier.
+ *
+ * Disable if you run into name conflicts and want to really remove the
+ * error_strerror()
+ */
+#define POLARSSL_ERROR_STRERROR_DUMMY
+
+/**
+ * \def POLARSSL_GENPRIME
+ *
+ * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C
+ *
+ * Enable the RSA prime-number generation code.
+ */
+#define POLARSSL_GENPRIME
+
+/**
+ * \def POLARSSL_FS_IO
+ *
+ * Enable functions that use the filesystem.
+ */
+#define POLARSSL_FS_IO
+
+/**
+ * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ * Do not add default entropy sources. These are the platform specific,
+ * hardclock and HAVEGE based poll functions.
+ *
+ * This is useful to have more control over the added entropy sources in an
+ * application.
+ *
+ * Uncomment this macro to prevent loading of default entropy functions.
+#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES
+ */
+
+/**
+ * \def POLARSSL_NO_PLATFORM_ENTROPY
+ *
+ * Do not use built-in platform entropy functions.
+ * This is useful if your platform does not support
+ * standards like the /dev/urandom or Windows CryptoAPI.
+ *
+ * Uncomment this macro to disable the built-in platform entropy functions.
+#define POLARSSL_NO_PLATFORM_ENTROPY
+ */
+
+/**
+ * \def POLARSSL_PKCS1_V21
+ *
+ * Requires: POLARSSL_MD_C, POLARSSL_RSA_C
+ *
+ * Enable support for PKCS#1 v2.1 encoding.
+ * This enables support for RSAES-OAEP and RSASSA-PSS operations.
+ */
+#define POLARSSL_PKCS1_V21
+
+/**
+ * \def POLARSSL_RSA_NO_CRT
+ *
+ * Do not use the Chinese Remainder Theorem for the RSA private operation.
+ *
+ * Uncomment this macro to disable the use of CRT in RSA.
+ *
+#define POLARSSL_RSA_NO_CRT
+ */
+
+/**
+ * \def POLARSSL_SELF_TEST
+ *
+ * Enable the checkup functions (*_self_test).
+ */
+#define POLARSSL_SELF_TEST
+
+/**
+ * \def POLARSSL_SSL_ALL_ALERT_MESSAGES
+ *
+ * Enable sending of alert messages in case of encountered errors as per RFC.
+ * If you choose not to send the alert messages, PolarSSL can still communicate
+ * with other servers, only debugging of failures is harder.
+ *
+ * The advantage of not sending alert messages, is that no information is given
+ * about reasons for failures thus preventing adversaries of gaining intel.
+ *
+ * Enable sending of all alert messages
+ */
+#define POLARSSL_SSL_ALERT_MESSAGES
+
+/**
+ * \def POLARSSL_SSL_DEBUG_ALL
+ *
+ * Enable the debug messages in SSL module for all issues.
+ * Debug messages have been disabled in some places to prevent timing
+ * attacks due to (unbalanced) debugging function calls.
+ *
+ * If you need all error reporting you should enable this during debugging,
+ * but remove this for production servers that should log as well.
+ *
+ * Uncomment this macro to report all debug messages on errors introducing
+ * a timing side-channel.
+ *
+#define POLARSSL_SSL_DEBUG_ALL
+ */
+
+/**
+ * \def POLARSSL_SSL_HW_RECORD_ACCEL
+ *
+ * Enable hooking functions in SSL module for hardware acceleration of
+ * individual records.
+ *
+ * Uncomment this macro to enable hooking functions.
+#define POLARSSL_SSL_HW_RECORD_ACCEL
+ */
+
+/**
+ * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
+ *
+ * Enable support for receiving and parsing SSLv2 Client Hello messages for the
+ * SSL Server module (POLARSSL_SSL_SRV_C)
+ *
+ * Comment this macro to disable support for SSLv2 Client Hello messages.
+ */
+#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
+
+/**
+ * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering an unknown critical extension.
+ *
+ * Uncomment to prevent an error.
+ *
+#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+ */
+
+/**
+ * \def POLARSSL_ZLIB_SUPPORT
+ *
+ * If set, the SSL/TLS module uses ZLIB to support compression and
+ * decompression of packet data.
+ *
+ * Used in: library/ssl_tls.c
+ * library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * This feature requires zlib library and headers to be present.
+ *
+ * Uncomment to enable use of ZLIB
+#define POLARSSL_ZLIB_SUPPORT
+ */
+/* \} name */
+
+/**
+ * \name SECTION: PolarSSL modules
+ *
+ * This section enables or disables entire modules in PolarSSL
+ * \{
+ */
+
+/**
+ * \def POLARSSL_AES_C
+ *
+ * Enable the AES block cipher.
+ *
+ * Module: library/aes.c
+ * Caller: library/ssl_tls.c
+ * library/pem.c
+ * library/ctr_drbg.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ * TLS_RSA_WITH_AES_128_CBC_SHA
+ * TLS_RSA_WITH_AES_256_CBC_SHA
+ * TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ * TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ * TLS_RSA_WITH_AES_128_CBC_SHA256
+ * TLS_RSA_WITH_AES_256_CBC_SHA256
+ * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ * TLS_RSA_WITH_AES_128_GCM_SHA256
+ * TLS_RSA_WITH_AES_256_GCM_SHA384
+ *
+ * PEM uses AES for decrypting encrypted keys.
+ */
+#define POLARSSL_AES_C
+
+/**
+ * \def POLARSSL_ARC4_C
+ *
+ * Enable the ARCFOUR stream cipher.
+ *
+ * Module: library/arc4.c
+ * Caller: library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ * TLS_RSA_WITH_RC4_128_MD5
+ * TLS_RSA_WITH_RC4_128_SHA
+ */
+#define POLARSSL_ARC4_C
+
+/**
+ * \def POLARSSL_ASN1_PARSE_C
+ *
+ * Enable the generic ASN1 parser.
+ *
+ * Module: library/asn1.c
+ * Caller: library/x509parse.c
+ */
+#define POLARSSL_ASN1_PARSE_C
+
+/**
+ * \def POLARSSL_ASN1_WRITE_C
+ *
+ * Enable the generic ASN1 writer.
+ *
+ * Module: library/asn1write.c
+ */
+#define POLARSSL_ASN1_WRITE_C
+
+/**
+ * \def POLARSSL_BASE64_C
+ *
+ * Enable the Base64 module.
+ *
+ * Module: library/base64.c
+ * Caller: library/pem.c
+ *
+ * This module is required for PEM support (required by X.509).
+ */
+#define POLARSSL_BASE64_C
+
+/**
+ * \def POLARSSL_BIGNUM_C
+ *
+ * Enable the multi-precision integer library.
+ *
+ * Module: library/bignum.c
+ * Caller: library/dhm.c
+ * library/rsa.c
+ * library/ssl_tls.c
+ * library/x509parse.c
+ *
+ * This module is required for RSA and DHM support.
+ */
+#define POLARSSL_BIGNUM_C
+
+/**
+ * \def POLARSSL_BLOWFISH_C
+ *
+ * Enable the Blowfish block cipher.
+ *
+ * Module: library/blowfish.c
+ */
+#define POLARSSL_BLOWFISH_C
+
+/**
+ * \def POLARSSL_CAMELLIA_C
+ *
+ * Enable the Camellia block cipher.
+ *
+ * Module: library/camellia.c
+ * Caller: library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+ * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+ * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ */
+#define POLARSSL_CAMELLIA_C
+
+/**
+ * \def POLARSSL_CERTS_C
+ *
+ * Enable the test certificates.
+ *
+ * Module: library/certs.c
+ * Caller:
+ *
+ * This module is used for testing (ssl_client/server).
+ */
+#define POLARSSL_CERTS_C
+
+/**
+ * \def POLARSSL_CIPHER_C
+ *
+ * Enable the generic cipher layer.
+ *
+ * Module: library/cipher.c
+ * Caller:
+ *
+ * Uncomment to enable generic cipher wrappers.
+ */
+#define POLARSSL_CIPHER_C
+
+/**
+ * \def POLARSSL_CTR_DRBG_C
+ *
+ * Enable the CTR_DRBG AES-256-based random generator
+ *
+ * Module: library/ctr_drbg.c
+ * Caller:
+ *
+ * Requires: POLARSSL_AES_C
+ *
+ * This module provides the CTR_DRBG AES-256 random number generator.
+ */
+#define POLARSSL_CTR_DRBG_C
+
+/**
+ * \def POLARSSL_DEBUG_C
+ *
+ * Enable the debug functions.
+ *
+ * Module: library/debug.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ *
+ * This module provides debugging functions.
+ */
+#define POLARSSL_DEBUG_C
+
+/**
+ * \def POLARSSL_DES_C
+ *
+ * Enable the DES block cipher.
+ *
+ * Module: library/des.c
+ * Caller: library/pem.c
+ * library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ * TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *
+ * PEM uses DES/3DES for decrypting encrypted keys.
+ */
+#define POLARSSL_DES_C
+
+/**
+ * \def POLARSSL_DHM_C
+ *
+ * Enable the Diffie-Hellman-Merkle key exchange.
+ *
+ * Module: library/dhm.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ * TLS_DHE_RSA_WITH_DES_CBC_SHA
+ * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ * TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ * TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ */
+#define POLARSSL_DHM_C
+
+/**
+ * \def POLARSSL_ENTROPY_C
+ *
+ * Enable the platform-specific entropy code.
+ *
+ * Module: library/entropy.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SHA4_C
+ *
+ * This module provides a generic entropy pool
+ */
+#define POLARSSL_ENTROPY_C
+
+/**
+ * \def POLARSSL_ERROR_C
+ *
+ * Enable error code to error string conversion.
+ *
+ * Module: library/error.c
+ * Caller:
+ *
+ * This module enables err_strerror().
+ */
+#define POLARSSL_ERROR_C
+
+/**
+ * \def POLARSSL_GCM_C
+ *
+ * Enable the Galois/Counter Mode (GCM) for AES
+ *
+ * Module: library/gcm.c
+ *
+ * Requires: POLARSSL_AES_C
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ * TLS_RSA_WITH_AES_128_GCM_SHA256
+ * TLS_RSA_WITH_AES_256_GCM_SHA384
+ */
+#define POLARSSL_GCM_C
+
+/**
+ * \def POLARSSL_HAVEGE_C
+ *
+ * Enable the HAVEGE random generator.
+ *
+ * Warning: the HAVEGE random generator is not suitable for virtualized
+ * environments
+ *
+ * Warning: the HAVEGE random generator is dependent on timing and specific
+ * processor traits. It is therefore not advised to use HAVEGE as
+ * your applications primary random generator or primary entropy pool
+ * input. As a secondary input to your entropy pool, it IS able add
+ * the (limited) extra entropy it provides.
+ *
+ * Module: library/havege.c
+ * Caller:
+ *
+ * Requires: POLARSSL_TIMING_C
+ *
+ * Uncomment to enable the HAVEGE random generator.
+#define POLARSSL_HAVEGE_C
+ */
+
+/**
+ * \def POLARSSL_MD_C
+ *
+ * Enable the generic message digest layer.
+ *
+ * Module: library/md.c
+ * Caller:
+ *
+ * Uncomment to enable generic message digest wrappers.
+ */
+#define POLARSSL_MD_C
+
+/**
+ * \def POLARSSL_MD2_C
+ *
+ * Enable the MD2 hash algorithm
+ *
+ * Module: library/md2.c
+ * Caller: library/x509parse.c
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ *
+#define POLARSSL_MD2_C
+ */
+
+/**
+ * \def POLARSSL_MD4_C
+ *
+ * Enable the MD4 hash algorithm
+ *
+ * Module: library/md4.c
+ * Caller: library/x509parse.c
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ *
+#define POLARSSL_MD4_C
+ */
+
+/**
+ * \def POLARSSL_MD5_C
+ *
+ * Enable the MD5 hash algorithm
+ *
+ * Module: library/md5.c
+ * Caller: library/pem.c
+ * library/ssl_tls.c
+ * library/x509parse.c
+ *
+ * This module is required for SSL/TLS and X.509.
+ * PEM uses MD5 for decrypting encrypted keys.
+ */
+#define POLARSSL_MD5_C
+
+/**
+ * \def POLARSSL_NET_C
+ *
+ * Enable the TCP/IP networking routines.
+ *
+ * Module: library/net.c
+ * Caller:
+ *
+ * This module provides TCP/IP networking routines.
+ */
+#define POLARSSL_NET_C
+
+/**
+ * \def POLARSSL_PADLOCK_C
+ *
+ * Enable VIA Padlock support on x86.
+ *
+ * Module: library/padlock.c
+ * Caller: library/aes.c
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+#define POLARSSL_PADLOCK_C
+
+/**
+ * \def POLARSSL_PBKDF2_C
+ *
+ * Enable PKCS#5 PBKDF2 key derivation function
+ * DEPRECATED: Use POLARSSL_PKCS5_C instead
+ *
+ * Module: library/pbkdf2.c
+ *
+ * Requires: POLARSSL_PKCS5_C
+ *
+ * This module adds support for the PKCS#5 PBKDF2 key derivation function.
+#define POLARSSL_PBKDF2_C
+ */
+
+/**
+ * \def POLARSSL_PEM_C
+ *
+ * Enable PEM decoding
+ *
+ * Module: library/pem.c
+ * Caller: library/x509parse.c
+ *
+ * Requires: POLARSSL_BASE64_C
+ *
+ * This modules adds support for decoding PEM files.
+ */
+#define POLARSSL_PEM_C
+
+/**
+ * \def POLARSSL_PKCS5_C
+ *
+ * Enable PKCS#5 functions
+ *
+ * Module: library/pkcs5.c
+ *
+ * Requires: POLARSSL_MD_C
+ *
+ * This module adds support for the PKCS#5 functions.
+ */
+#define POLARSSL_PKCS5_C
+
+/**
+ * \def POLARSSL_PKCS11_C
+ *
+ * Enable wrapper for PKCS#11 smartcard support.
+ *
+ * Module: library/ssl_srv.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module enables SSL/TLS PKCS #11 smartcard support.
+ * Requires the presence of the PKCS#11 helper library (libpkcs11-helper)
+#define POLARSSL_PKCS11_C
+ */
+
+/**
+ * \def POLARSSL_PKCS12_C
+ *
+ * Enable PKCS#12 PBE functions
+ * Adds algorithms for parsing PKCS#8 encrypted private keys
+ *
+ * Module: library/pkcs12.c
+ * Caller: library/x509parse.c
+ *
+ * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_CIPHER_C, POLARSSL_MD_C
+ * Can use: POLARSSL_ARC4_C
+ *
+ * This module enables PKCS#12 functions.
+ */
+#define POLARSSL_PKCS12_C
+
+/**
+ * \def POLARSSL_RSA_C
+ *
+ * Enable the RSA public-key cryptosystem.
+ *
+ * Module: library/rsa.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ * library/x509.c
+ *
+ * Requires: POLARSSL_BIGNUM_C
+ *
+ * This module is required for SSL/TLS and MD5-signed certificates.
+ */
+#define POLARSSL_RSA_C
+
+/**
+ * \def POLARSSL_SHA1_C
+ *
+ * Enable the SHA1 cryptographic hash algorithm.
+ *
+ * Module: library/sha1.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ * library/x509parse.c
+ *
+ * This module is required for SSL/TLS and SHA1-signed certificates.
+ */
+#define POLARSSL_SHA1_C
+
+/**
+ * \def POLARSSL_SHA2_C
+ *
+ * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
+ *
+ * Module: library/sha2.c
+ * Caller: library/md_wrap.c
+ * library/x509parse.c
+ *
+ * This module adds support for SHA-224 and SHA-256.
+ * This module is required for the SSL/TLS 1.2 PRF function.
+ */
+#define POLARSSL_SHA2_C
+
+/**
+ * \def POLARSSL_SHA4_C
+ *
+ * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
+ *
+ * Module: library/sha4.c
+ * Caller: library/md_wrap.c
+ * library/x509parse.c
+ *
+ * This module adds support for SHA-384 and SHA-512.
+ */
+#define POLARSSL_SHA4_C
+
+/**
+ * \def POLARSSL_SSL_CACHE_C
+ *
+ * Enable simple SSL cache implementation.
+ *
+ * Module: library/ssl_cache.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_CACHE_C
+ */
+#define POLARSSL_SSL_CACHE_C
+
+/**
+ * \def POLARSSL_SSL_CLI_C
+ *
+ * Enable the SSL/TLS client code.
+ *
+ * Module: library/ssl_cli.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS client support.
+ */
+#define POLARSSL_SSL_CLI_C
+
+/**
+ * \def POLARSSL_SSL_SRV_C
+ *
+ * Enable the SSL/TLS server code.
+ *
+ * Module: library/ssl_srv.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS server support.
+ */
+#define POLARSSL_SSL_SRV_C
+
+/**
+ * \def POLARSSL_SSL_TLS_C
+ *
+ * Enable the generic SSL/TLS code.
+ *
+ * Module: library/ssl_tls.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * Requires: POLARSSL_MD5_C, POLARSSL_SHA1_C, POLARSSL_X509_PARSE_C
+ *
+ * This module is required for SSL/TLS.
+ */
+#define POLARSSL_SSL_TLS_C
+
+/**
+ * \def POLARSSL_TIMING_C
+ *
+ * Enable the portable timing interface.
+ *
+ * Module: library/timing.c
+ * Caller: library/havege.c
+ *
+ * This module is used by the HAVEGE random number generator.
+ */
+#define POLARSSL_TIMING_C
+
+/**
+ * \def POLARSSL_VERSION_C
+ *
+ * Enable run-time version information.
+ *
+ * Module: library/version.c
+ *
+ * This module provides run-time version information.
+ */
+#define POLARSSL_VERSION_C
+
+/**
+ * \def POLARSSL_X509_PARSE_C
+ *
+ * Enable X.509 certificate parsing.
+ *
+ * Module: library/x509parse.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ *
+ * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_RSA_C
+ *
+ * This module is required for X.509 certificate parsing.
+ */
+#define POLARSSL_X509_PARSE_C
+
+/**
+ * \def POLARSSL_X509_WRITE_C
+ *
+ * Enable X.509 buffer writing.
+ *
+ * Module: library/x509write.c
+ *
+ * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C
+ *
+ * This module is required for X.509 certificate request writing.
+ */
+#define POLARSSL_X509_WRITE_C
+
+/**
+ * \def POLARSSL_XTEA_C
+ *
+ * Enable the XTEA block cipher.
+ *
+ * Module: library/xtea.c
+ * Caller:
+ */
+#define POLARSSL_XTEA_C
+/* \} name */
+
+/**
+ * \name SECTION: Module configuration options
+ *
+ * This section allows for the setting of module specific sizes and
+ * configuration options. The default values are already present in the
+ * relevant header files and should suffice for the regular use cases.
+ * Our advice is to enable POLARSSL_CONFIG_OPTIONS and change values here
+ * only if you have a good reason and know the consequences.
+ *
+ * If POLARSSL_CONFIG_OPTIONS is undefined here the options in the module
+ * header file take precedence.
+ *
+ * Please check the respective header file for documentation on these
+ * parameters (to prevent duplicate documentation).
+ *
+ * Uncomment POLARSSL_CONFIG_OPTIONS to enable using the values defined here.
+ * \{
+ */
+//#define POLARSSL_CONFIG_OPTIONS /**< Enable config.h module value configuration */
+
+#if defined(POLARSSL_CONFIG_OPTIONS)
+
+// MPI / BIGNUM options
+//
+#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */
+#define POLARSSL_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */
+
+// CTR_DRBG options
+//
+#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default */
+#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
+#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
+#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
+#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
+
+// Entropy options
+//
+#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */
+#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */
+
+// SSL Cache options
+//
+#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */
+#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */
+
+// SSL options
+//
+#define SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */
+
+#endif /* POLARSSL_CONFIG_OPTIONS */
+
+/* \} name */
+#endif /* config.h */
diff --git a/polarssl/ctr_drbg.c b/polarssl/ctr_drbg.c
new file mode 100644
index 0000000..8cf0371
--- /dev/null
+++ b/polarssl/ctr_drbg.c
@@ -0,0 +1,562 @@
+/*
+ * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The NIST SP 800-90 DRBGs are described in the following publucation.
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_CTR_DRBG_C)
+
+#include "polarssl/ctr_drbg.h"
+
+#if defined(POLARSSL_FS_IO)
+#include
+#endif
+
+/*
+ * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
+ * tests to succeed (which require known length fixed entropy)
+ */
+int ctr_drbg_init_entropy_len(
+ ctr_drbg_context *ctx,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len,
+ size_t entropy_len )
+{
+ int ret;
+ unsigned char key[CTR_DRBG_KEYSIZE];
+
+ memset( ctx, 0, sizeof(ctr_drbg_context) );
+ memset( key, 0, CTR_DRBG_KEYSIZE );
+
+ ctx->f_entropy = f_entropy;
+ ctx->p_entropy = p_entropy;
+
+ ctx->entropy_len = entropy_len;
+ ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
+
+ /*
+ * Initialize with an empty key
+ */
+ aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
+
+ if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
+ return( ret );
+
+ return( 0 );
+}
+
+int ctr_drbg_init( ctr_drbg_context *ctx,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len )
+{
+ return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
+ CTR_DRBG_ENTROPY_LEN ) );
+}
+
+void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
+{
+ ctx->prediction_resistance = resistance;
+}
+
+void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
+{
+ ctx->entropy_len = len;
+}
+
+void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
+{
+ ctx->reseed_interval = interval;
+}
+
+int block_cipher_df( unsigned char *output,
+ const unsigned char *data, size_t data_len )
+{
+ unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
+ unsigned char tmp[CTR_DRBG_SEEDLEN];
+ unsigned char key[CTR_DRBG_KEYSIZE];
+ unsigned char chain[CTR_DRBG_BLOCKSIZE];
+ unsigned char *p = buf, *iv;
+ aes_context aes_ctx;
+
+ int i, j, buf_len, use_len;
+
+ memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
+
+ /*
+ * Construct IV (16 bytes) and S in buffer
+ * IV = Counter (in 32-bits) padded to 16 with zeroes
+ * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
+ * data || 0x80
+ * (Total is padded to a multiple of 16-bytes with zeroes)
+ */
+ p = buf + CTR_DRBG_BLOCKSIZE;
+ *p++ = ( data_len >> 24 ) & 0xff;
+ *p++ = ( data_len >> 16 ) & 0xff;
+ *p++ = ( data_len >> 8 ) & 0xff;
+ *p++ = ( data_len ) & 0xff;
+ p += 3;
+ *p++ = CTR_DRBG_SEEDLEN;
+ memcpy( p, data, data_len );
+ p[data_len] = 0x80;
+
+ buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
+
+ for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
+ key[i] = i;
+
+ aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
+
+ /*
+ * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
+ */
+ for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
+ {
+ p = buf;
+ memset( chain, 0, CTR_DRBG_BLOCKSIZE );
+ use_len = buf_len;
+
+ while( use_len > 0 )
+ {
+ for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
+ chain[i] ^= p[i];
+ p += CTR_DRBG_BLOCKSIZE;
+ use_len -= CTR_DRBG_BLOCKSIZE;
+
+ aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
+ }
+
+ memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
+
+ /*
+ * Update IV
+ */
+ buf[3]++;
+ }
+
+ /*
+ * Do final encryption with reduced data
+ */
+ aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
+ iv = tmp + CTR_DRBG_KEYSIZE;
+ p = output;
+
+ for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
+ {
+ aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
+ memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
+ p += CTR_DRBG_BLOCKSIZE;
+ }
+
+ return( 0 );
+}
+
+int ctr_drbg_update_internal( ctr_drbg_context *ctx,
+ const unsigned char data[CTR_DRBG_SEEDLEN] )
+{
+ unsigned char tmp[CTR_DRBG_SEEDLEN];
+ unsigned char *p = tmp;
+ int i, j;
+
+ memset( tmp, 0, CTR_DRBG_SEEDLEN );
+
+ for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
+ {
+ /*
+ * Increase counter
+ */
+ for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
+ if( ++ctx->counter[i - 1] != 0 )
+ break;
+
+ /*
+ * Crypt counter block
+ */
+ aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
+
+ p += CTR_DRBG_BLOCKSIZE;
+ }
+
+ for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
+ tmp[i] ^= data[i];
+
+ /*
+ * Update key and counter
+ */
+ aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
+ memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
+
+ return( 0 );
+}
+
+void ctr_drbg_update( ctr_drbg_context *ctx,
+ const unsigned char *additional, size_t add_len )
+{
+ unsigned char add_input[CTR_DRBG_SEEDLEN];
+
+ if( add_len > 0 )
+ {
+ block_cipher_df( add_input, additional, add_len );
+ ctr_drbg_update_internal( ctx, add_input );
+ }
+}
+
+int ctr_drbg_reseed( ctr_drbg_context *ctx,
+ const unsigned char *additional, size_t len )
+{
+ unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
+ size_t seedlen = 0;
+
+ if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
+ return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+ memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
+
+ /*
+ * Gather enropy_len bytes of entropy to seed state
+ */
+ if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
+ ctx->entropy_len ) )
+ {
+ return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
+ }
+
+ seedlen += ctx->entropy_len;
+
+ /*
+ * Add additional data
+ */
+ if( additional && len )
+ {
+ memcpy( seed + seedlen, additional, len );
+ seedlen += len;
+ }
+
+ /*
+ * Reduce to 384 bits
+ */
+ block_cipher_df( seed, seed, seedlen );
+
+ /*
+ * Update state
+ */
+ ctr_drbg_update_internal( ctx, seed );
+ ctx->reseed_counter = 1;
+
+ return( 0 );
+}
+
+int ctr_drbg_random_with_add( void *p_rng,
+ unsigned char *output, size_t output_len,
+ const unsigned char *additional, size_t add_len )
+{
+ int ret = 0;
+ ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
+ unsigned char add_input[CTR_DRBG_SEEDLEN];
+ unsigned char *p = output;
+ unsigned char tmp[CTR_DRBG_BLOCKSIZE];
+ int i;
+ size_t use_len;
+
+ if( output_len > CTR_DRBG_MAX_REQUEST )
+ return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
+
+ if( add_len > CTR_DRBG_MAX_INPUT )
+ return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+ memset( add_input, 0, CTR_DRBG_SEEDLEN );
+
+ if( ctx->reseed_counter > ctx->reseed_interval ||
+ ctx->prediction_resistance )
+ {
+ if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
+ return( ret );
+
+ add_len = 0;
+ }
+
+ if( add_len > 0 )
+ {
+ block_cipher_df( add_input, additional, add_len );
+ ctr_drbg_update_internal( ctx, add_input );
+ }
+
+ while( output_len > 0 )
+ {
+ /*
+ * Increase counter
+ */
+ for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
+ if( ++ctx->counter[i - 1] != 0 )
+ break;
+
+ /*
+ * Crypt counter block
+ */
+ aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
+
+ use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
+ /*
+ * Copy random block to destination
+ */
+ memcpy( p, tmp, use_len );
+ p += use_len;
+ output_len -= use_len;
+ }
+
+ ctr_drbg_update_internal( ctx, add_input );
+
+ ctx->reseed_counter++;
+
+ return( 0 );
+}
+
+int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
+{
+ return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
+}
+
+#if defined(POLARSSL_FS_IO)
+int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
+{
+ int ret;
+ FILE *f;
+ unsigned char buf[ CTR_DRBG_MAX_INPUT ];
+
+ if( ( f = fopen( path, "wb" ) ) == NULL )
+ return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
+
+ if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
+ return( ret );
+
+ if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+
+int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
+{
+ FILE *f;
+ size_t n;
+ unsigned char buf[ CTR_DRBG_MAX_INPUT ];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
+
+ fseek( f, 0, SEEK_END );
+ n = (size_t) ftell( f );
+ fseek( f, 0, SEEK_SET );
+
+ if( n > CTR_DRBG_MAX_INPUT )
+ return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+ if( fread( buf, 1, n, f ) != n )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
+ }
+
+ ctr_drbg_update( ctx, buf, n );
+
+ fclose( f );
+
+ return( ctr_drbg_write_seed_file( ctx, path ) );
+}
+#endif /* POLARSSL_FS_IO */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include
+
+unsigned char entropy_source_pr[96] =
+ { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
+ 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
+ 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
+ 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
+ 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
+ 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
+ 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
+ 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
+ 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
+ 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
+ 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
+ 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
+
+unsigned char entropy_source_nopr[64] =
+ { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
+ 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
+ 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
+ 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
+ 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
+ 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
+ 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
+ 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
+
+unsigned char nonce_pers_pr[16] =
+ { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
+ 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
+
+unsigned char nonce_pers_nopr[16] =
+ { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
+ 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
+
+unsigned char result_pr[16] =
+ { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
+ 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
+
+unsigned char result_nopr[16] =
+ { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
+ 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
+
+int test_offset;
+int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, size_t len )
+{
+ unsigned char *p = data;
+ memcpy( buf, p + test_offset, len );
+ test_offset += 32;
+ return( 0 );
+}
+
+/*
+ * Checkup routine
+ */
+int ctr_drbg_self_test( int verbose )
+{
+ ctr_drbg_context ctx;
+ unsigned char buf[16];
+
+ /*
+ * Based on a NIST CTR_DRBG test vector (PR = True)
+ */
+ if( verbose != 0 )
+ printf( " CTR_DRBG (PR = TRUE) : " );
+
+ test_offset = 0;
+ if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16, 32 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
+
+ if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ /*
+ * Based on a NIST CTR_DRBG test vector (PR = FALSE)
+ */
+ if( verbose != 0 )
+ printf( " CTR_DRBG (PR = FALSE): " );
+
+ test_offset = 0;
+ if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16, 32 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( memcmp( buf, result_nopr, 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+#endif
+
+#endif
diff --git a/polarssl/ctr_drbg.h b/polarssl/ctr_drbg.h
new file mode 100644
index 0000000..c75feda
--- /dev/null
+++ b/polarssl/ctr_drbg.h
@@ -0,0 +1,231 @@
+/**
+ * \file ctr_drbg.h
+ *
+ * \brief CTR_DRBG based on AES-256 (NIST SP 800-90)
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CTR_DRBG_H
+#define POLARSSL_CTR_DRBG_H
+
+#include
+
+#include "polarssl/aes.h"
+
+#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */
+#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< Too many random requested in single call. */
+#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< Input too large (Entropy + additional). */
+#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read/write error in file. */
+
+#define CTR_DRBG_BLOCKSIZE 16 /**< Block size used by the cipher */
+#define CTR_DRBG_KEYSIZE 32 /**< Key size used by the cipher */
+#define CTR_DRBG_KEYBITS ( CTR_DRBG_KEYSIZE * 8 )
+#define CTR_DRBG_SEEDLEN ( CTR_DRBG_KEYSIZE + CTR_DRBG_BLOCKSIZE )
+ /**< The seed length (counter + AES key) */
+
+#if !defined(POLARSSL_CONFIG_OPTIONS)
+#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default */
+#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
+#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
+#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
+#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
+#endif /* !POLARSSL_CONFIG_OPTIONS */
+
+#define CTR_DRBG_PR_OFF 0 /**< No prediction resistance */
+#define CTR_DRBG_PR_ON 1 /**< Prediction resistance enabled */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief CTR_DRBG context structure
+ */
+typedef struct
+{
+ unsigned char counter[16]; /*!< counter (V) */
+ int reseed_counter; /*!< reseed counter */
+ int prediction_resistance; /*!< enable prediction resistance (Automatic
+ reseed before every random generation) */
+ size_t entropy_len; /*!< amount of entropy grabbed on each (re)seed */
+ int reseed_interval; /*!< reseed interval */
+
+ aes_context aes_ctx; /*!< AES context */
+
+ /*
+ * Callbacks (Entropy)
+ */
+ int (*f_entropy)(void *, unsigned char *, size_t);
+
+ void *p_entropy; /*!< context for the entropy function */
+}
+ctr_drbg_context;
+
+/**
+ * \brief CTR_DRBG initialization
+ *
+ * Note: Personalization data can be provided in addition to the more generic
+ * entropy source to make this instantiation as unique as possible.
+ *
+ * \param ctx CTR_DRBG context to be initialized
+ * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer
+ * length)
+ * \param p_entropy Entropy context
+ * \param custom Personalization data (Device specific identifiers)
+ * (Can be NULL)
+ * \param len Length of personalization data
+ *
+ * \return 0 if successful, or
+ * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int ctr_drbg_init( ctr_drbg_context *ctx,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len );
+
+/**
+ * \brief Enable / disable prediction resistance (Default: Off)
+ *
+ * Note: If enabled, entropy is used for ctx->entropy_len before each call!
+ * Only use this if you have ample supply of good entropy!
+ *
+ * \param ctx CTR_DRBG context
+ * \param resistance CTR_DRBG_PR_ON or CTR_DRBG_PR_OFF
+ */
+void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx,
+ int resistance );
+
+/**
+ * \brief Set the amount of entropy grabbed on each (re)seed
+ * (Default: CTR_DRBG_ENTROPY_LEN)
+ *
+ * \param ctx CTR_DRBG context
+ * \param len Amount of entropy to grab
+ */
+void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx,
+ size_t len );
+
+/**
+ * \brief Set the reseed interval
+ * (Default: CTR_DRBG_RESEED_INTERVAL)
+ *
+ * \param ctx CTR_DRBG context
+ * \param interval Reseed interval
+ */
+void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx,
+ int interval );
+
+/**
+ * \brief CTR_DRBG reseeding (extracts data from entropy source)
+ *
+ * \param ctx CTR_DRBG context
+ * \param additional Additional data to add to state (Can be NULL)
+ * \param len Length of additional data
+ *
+ * \return 0 if successful, or
+ * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int ctr_drbg_reseed( ctr_drbg_context *ctx,
+ const unsigned char *additional, size_t len );
+
+/**
+ * \brief CTR_DRBG update state
+ *
+ * \param ctx CTR_DRBG context
+ * \param additional Additional data to update state with
+ * \param add_len Length of additional data
+ */
+void ctr_drbg_update( ctr_drbg_context *ctx,
+ const unsigned char *additional, size_t add_len );
+
+/**
+ * \brief CTR_DRBG generate random with additional update input
+ *
+ * Note: Automatically reseeds if reseed_counter is reached.
+ *
+ * \param p_rng CTR_DRBG context
+ * \param output Buffer to fill
+ * \param output_len Length of the buffer
+ * \param additional Additional data to update with (Can be NULL)
+ * \param add_len Length of additional data
+ *
+ * \return 0 if successful, or
+ * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or
+ * POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG
+ */
+int ctr_drbg_random_with_add( void *p_rng,
+ unsigned char *output, size_t output_len,
+ const unsigned char *additional, size_t add_len );
+
+/**
+ * \brief CTR_DRBG generate random
+ *
+ * Note: Automatically reseeds if reseed_counter is reached.
+ *
+ * \param p_rng CTR_DRBG context
+ * \param output Buffer to fill
+ * \param output_len Length of the buffer
+ *
+ * \return 0 if successful, or
+ * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or
+ * POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG
+ */
+int ctr_drbg_random( void *p_rng,
+ unsigned char *output, size_t output_len );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief Write a seed file
+ *
+ * \param path Name of the file
+ *
+ * \return 0 if successful, 1 on file error, or
+ * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path );
+
+/**
+ * \brief Read and update a seed file. Seed is added to this
+ * instance
+ *
+ * \param path Name of the file
+ *
+ * \return 0 if successful, 1 on file error,
+ * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
+ * POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG
+ */
+int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path );
+#endif
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int ctr_drbg_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ctr_drbg.h */
diff --git a/polarssl/debug.c b/polarssl/debug.c
new file mode 100644
index 0000000..81ee649
--- /dev/null
+++ b/polarssl/debug.c
@@ -0,0 +1,238 @@
+/*
+ * Debugging routines
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_DEBUG_C)
+
+#include "polarssl/debug.h"
+
+#include
+#include
+
+#if defined _MSC_VER && !defined snprintf
+#define snprintf _snprintf
+#endif
+
+#if defined _MSC_VER && !defined vsnprintf
+#define vsnprintf _vsnprintf
+#endif
+
+char *debug_fmt( const char *format, ... )
+{
+ va_list argp;
+ static char str[512];
+ int maxlen = sizeof( str ) - 1;
+
+ va_start( argp, format );
+ vsnprintf( str, maxlen, format, argp );
+ va_end( argp );
+
+ str[maxlen] = '\0';
+ return( str );
+}
+
+void debug_print_msg( const ssl_context *ssl, int level,
+ const char *file, int line, const char *text )
+{
+ char str[512];
+ int maxlen = sizeof( str ) - 1;
+
+ if( ssl->f_dbg == NULL )
+ return;
+
+ snprintf( str, maxlen, "%s(%04d): %s\n", file, line, text );
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+}
+
+void debug_print_ret( const ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, int ret )
+{
+ char str[512];
+ int maxlen = sizeof( str ) - 1;
+
+ if( ssl->f_dbg == NULL )
+ return;
+
+ snprintf( str, maxlen, "%s(%04d): %s() returned %d (0x%x)\n",
+ file, line, text, ret, ret );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+}
+
+void debug_print_buf( const ssl_context *ssl, int level,
+ const char *file, int line, const char *text,
+ unsigned char *buf, size_t len )
+{
+ char str[512];
+ size_t i, maxlen = sizeof( str ) - 1;
+
+ if( ssl->f_dbg == NULL )
+ return;
+
+ snprintf( str, maxlen, "%s(%04d): dumping '%s' (%d bytes)\n",
+ file, line, text, (unsigned int) len );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+
+ for( i = 0; i < len; i++ )
+ {
+ if( i >= 4096 )
+ break;
+
+ if( i % 16 == 0 )
+ {
+ if( i > 0 )
+ ssl->f_dbg( ssl->p_dbg, level, "\n" );
+
+ snprintf( str, maxlen, "%s(%04d): %04x: ", file, line,
+ (unsigned int) i );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+ }
+
+ snprintf( str, maxlen, " %02x", (unsigned int) buf[i] );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+ }
+
+ if( len > 0 )
+ ssl->f_dbg( ssl->p_dbg, level, "\n" );
+}
+
+void debug_print_mpi( const ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, const mpi *X )
+{
+ char str[512];
+ int j, k, maxlen = sizeof( str ) - 1, zeros = 1;
+ size_t i, n;
+
+ if( ssl->f_dbg == NULL || X == NULL )
+ return;
+
+ for( n = X->n - 1; n > 0; n-- )
+ if( X->p[n] != 0 )
+ break;
+
+ for( j = ( sizeof(t_uint) << 3 ) - 1; j >= 0; j-- )
+ if( ( ( X->p[n] >> j ) & 1 ) != 0 )
+ break;
+
+ snprintf( str, maxlen, "%s(%04d): value of '%s' (%d bits) is:\n",
+ file, line, text,
+ (int) ( ( n * ( sizeof(t_uint) << 3 ) ) + j + 1 ) );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+
+ for( i = n + 1, j = 0; i > 0; i-- )
+ {
+ if( zeros && X->p[i - 1] == 0 )
+ continue;
+
+ for( k = sizeof( t_uint ) - 1; k >= 0; k-- )
+ {
+ if( zeros && ( ( X->p[i - 1] >> (k << 3) ) & 0xFF ) == 0 )
+ continue;
+ else
+ zeros = 0;
+
+ if( j % 16 == 0 )
+ {
+ if( j > 0 )
+ ssl->f_dbg( ssl->p_dbg, level, "\n" );
+
+ snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+ }
+
+ snprintf( str, maxlen, " %02x", (unsigned int)
+ ( X->p[i - 1] >> (k << 3) ) & 0xFF );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+
+ j++;
+ }
+
+ }
+
+ if( zeros == 1 )
+ {
+ snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+ ssl->f_dbg( ssl->p_dbg, level, " 00" );
+ }
+
+ ssl->f_dbg( ssl->p_dbg, level, "\n" );
+}
+
+void debug_print_crt( const ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, const x509_cert *crt )
+{
+ char str[1024], prefix[64];
+ int i = 0, maxlen = sizeof( prefix ) - 1;
+
+ if( ssl->f_dbg == NULL || crt == NULL )
+ return;
+
+ snprintf( prefix, maxlen, "%s(%04d): ", file, line );
+ prefix[maxlen] = '\0';
+ maxlen = sizeof( str ) - 1;
+
+ while( crt != NULL )
+ {
+ char buf[1024];
+ x509parse_cert_info( buf, sizeof( buf ) - 1, prefix, crt );
+
+ snprintf( str, maxlen, "%s(%04d): %s #%d:\n%s",
+ file, line, text, ++i, buf );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+
+ debug_print_mpi( ssl, level, file, line,
+ "crt->rsa.N", &crt->rsa.N );
+
+ debug_print_mpi( ssl, level, file, line,
+ "crt->rsa.E", &crt->rsa.E );
+
+ crt = crt->next;
+ }
+}
+
+#endif
diff --git a/polarssl/debug.h b/polarssl/debug.h
new file mode 100644
index 0000000..d85b6d3
--- /dev/null
+++ b/polarssl/debug.h
@@ -0,0 +1,89 @@
+/**
+ * \file debug.h
+ *
+ * \brief Debug functions
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_DEBUG_H
+#define POLARSSL_DEBUG_H
+
+#include "polarssl/config.h"
+#include "polarssl/ssl.h"
+
+#if defined(POLARSSL_DEBUG_C)
+
+#define SSL_DEBUG_MSG( level, args ) \
+ debug_print_msg( ssl, level, __FILE__, __LINE__, debug_fmt args );
+
+#define SSL_DEBUG_RET( level, text, ret ) \
+ debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret );
+
+#define SSL_DEBUG_BUF( level, text, buf, len ) \
+ debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len );
+
+#define SSL_DEBUG_MPI( level, text, X ) \
+ debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X );
+
+#define SSL_DEBUG_CRT( level, text, crt ) \
+ debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt );
+
+#else
+
+#define SSL_DEBUG_MSG( level, args ) do { } while( 0 )
+#define SSL_DEBUG_RET( level, text, ret ) do { } while( 0 )
+#define SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 )
+#define SSL_DEBUG_MPI( level, text, X ) do { } while( 0 )
+#define SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 )
+
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char *debug_fmt( const char *format, ... );
+
+void debug_print_msg( const ssl_context *ssl, int level,
+ const char *file, int line, const char *text );
+
+void debug_print_ret( const ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, int ret );
+
+void debug_print_buf( const ssl_context *ssl, int level,
+ const char *file, int line, const char *text,
+ unsigned char *buf, size_t len );
+
+void debug_print_mpi( const ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, const mpi *X );
+
+void debug_print_crt( const ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, const x509_cert *crt );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* debug.h */
diff --git a/polarssl/des.c b/polarssl/des.c
new file mode 100644
index 0000000..0cf4b3d
--- /dev/null
+++ b/polarssl/des.c
@@ -0,0 +1,997 @@
+/*
+ * FIPS-46-3 compliant Triple-DES implementation
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * DES, on which TDES is based, was originally designed by Horst Feistel
+ * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS).
+ *
+ * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_DES_C)
+
+#include "polarssl/des.h"
+
+#if !defined(POLARSSL_DES_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+/*
+ * Expanded DES S-boxes
+ */
+static const uint32_t SB1[64] =
+{
+ 0x01010400, 0x00000000, 0x00010000, 0x01010404,
+ 0x01010004, 0x00010404, 0x00000004, 0x00010000,
+ 0x00000400, 0x01010400, 0x01010404, 0x00000400,
+ 0x01000404, 0x01010004, 0x01000000, 0x00000004,
+ 0x00000404, 0x01000400, 0x01000400, 0x00010400,
+ 0x00010400, 0x01010000, 0x01010000, 0x01000404,
+ 0x00010004, 0x01000004, 0x01000004, 0x00010004,
+ 0x00000000, 0x00000404, 0x00010404, 0x01000000,
+ 0x00010000, 0x01010404, 0x00000004, 0x01010000,
+ 0x01010400, 0x01000000, 0x01000000, 0x00000400,
+ 0x01010004, 0x00010000, 0x00010400, 0x01000004,
+ 0x00000400, 0x00000004, 0x01000404, 0x00010404,
+ 0x01010404, 0x00010004, 0x01010000, 0x01000404,
+ 0x01000004, 0x00000404, 0x00010404, 0x01010400,
+ 0x00000404, 0x01000400, 0x01000400, 0x00000000,
+ 0x00010004, 0x00010400, 0x00000000, 0x01010004
+};
+
+static const uint32_t SB2[64] =
+{
+ 0x80108020, 0x80008000, 0x00008000, 0x00108020,
+ 0x00100000, 0x00000020, 0x80100020, 0x80008020,
+ 0x80000020, 0x80108020, 0x80108000, 0x80000000,
+ 0x80008000, 0x00100000, 0x00000020, 0x80100020,
+ 0x00108000, 0x00100020, 0x80008020, 0x00000000,
+ 0x80000000, 0x00008000, 0x00108020, 0x80100000,
+ 0x00100020, 0x80000020, 0x00000000, 0x00108000,
+ 0x00008020, 0x80108000, 0x80100000, 0x00008020,
+ 0x00000000, 0x00108020, 0x80100020, 0x00100000,
+ 0x80008020, 0x80100000, 0x80108000, 0x00008000,
+ 0x80100000, 0x80008000, 0x00000020, 0x80108020,
+ 0x00108020, 0x00000020, 0x00008000, 0x80000000,
+ 0x00008020, 0x80108000, 0x00100000, 0x80000020,
+ 0x00100020, 0x80008020, 0x80000020, 0x00100020,
+ 0x00108000, 0x00000000, 0x80008000, 0x00008020,
+ 0x80000000, 0x80100020, 0x80108020, 0x00108000
+};
+
+static const uint32_t SB3[64] =
+{
+ 0x00000208, 0x08020200, 0x00000000, 0x08020008,
+ 0x08000200, 0x00000000, 0x00020208, 0x08000200,
+ 0x00020008, 0x08000008, 0x08000008, 0x00020000,
+ 0x08020208, 0x00020008, 0x08020000, 0x00000208,
+ 0x08000000, 0x00000008, 0x08020200, 0x00000200,
+ 0x00020200, 0x08020000, 0x08020008, 0x00020208,
+ 0x08000208, 0x00020200, 0x00020000, 0x08000208,
+ 0x00000008, 0x08020208, 0x00000200, 0x08000000,
+ 0x08020200, 0x08000000, 0x00020008, 0x00000208,
+ 0x00020000, 0x08020200, 0x08000200, 0x00000000,
+ 0x00000200, 0x00020008, 0x08020208, 0x08000200,
+ 0x08000008, 0x00000200, 0x00000000, 0x08020008,
+ 0x08000208, 0x00020000, 0x08000000, 0x08020208,
+ 0x00000008, 0x00020208, 0x00020200, 0x08000008,
+ 0x08020000, 0x08000208, 0x00000208, 0x08020000,
+ 0x00020208, 0x00000008, 0x08020008, 0x00020200
+};
+
+static const uint32_t SB4[64] =
+{
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802080, 0x00800081, 0x00800001, 0x00002001,
+ 0x00000000, 0x00802000, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00800080, 0x00800001,
+ 0x00000001, 0x00002000, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002001, 0x00002080,
+ 0x00800081, 0x00000001, 0x00002080, 0x00800080,
+ 0x00002000, 0x00802080, 0x00802081, 0x00000081,
+ 0x00800080, 0x00800001, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00000000, 0x00802000,
+ 0x00002080, 0x00800080, 0x00800081, 0x00000001,
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802081, 0x00000081, 0x00000001, 0x00002000,
+ 0x00800001, 0x00002001, 0x00802080, 0x00800081,
+ 0x00002001, 0x00002080, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002000, 0x00802080
+};
+
+static const uint32_t SB5[64] =
+{
+ 0x00000100, 0x02080100, 0x02080000, 0x42000100,
+ 0x00080000, 0x00000100, 0x40000000, 0x02080000,
+ 0x40080100, 0x00080000, 0x02000100, 0x40080100,
+ 0x42000100, 0x42080000, 0x00080100, 0x40000000,
+ 0x02000000, 0x40080000, 0x40080000, 0x00000000,
+ 0x40000100, 0x42080100, 0x42080100, 0x02000100,
+ 0x42080000, 0x40000100, 0x00000000, 0x42000000,
+ 0x02080100, 0x02000000, 0x42000000, 0x00080100,
+ 0x00080000, 0x42000100, 0x00000100, 0x02000000,
+ 0x40000000, 0x02080000, 0x42000100, 0x40080100,
+ 0x02000100, 0x40000000, 0x42080000, 0x02080100,
+ 0x40080100, 0x00000100, 0x02000000, 0x42080000,
+ 0x42080100, 0x00080100, 0x42000000, 0x42080100,
+ 0x02080000, 0x00000000, 0x40080000, 0x42000000,
+ 0x00080100, 0x02000100, 0x40000100, 0x00080000,
+ 0x00000000, 0x40080000, 0x02080100, 0x40000100
+};
+
+static const uint32_t SB6[64] =
+{
+ 0x20000010, 0x20400000, 0x00004000, 0x20404010,
+ 0x20400000, 0x00000010, 0x20404010, 0x00400000,
+ 0x20004000, 0x00404010, 0x00400000, 0x20000010,
+ 0x00400010, 0x20004000, 0x20000000, 0x00004010,
+ 0x00000000, 0x00400010, 0x20004010, 0x00004000,
+ 0x00404000, 0x20004010, 0x00000010, 0x20400010,
+ 0x20400010, 0x00000000, 0x00404010, 0x20404000,
+ 0x00004010, 0x00404000, 0x20404000, 0x20000000,
+ 0x20004000, 0x00000010, 0x20400010, 0x00404000,
+ 0x20404010, 0x00400000, 0x00004010, 0x20000010,
+ 0x00400000, 0x20004000, 0x20000000, 0x00004010,
+ 0x20000010, 0x20404010, 0x00404000, 0x20400000,
+ 0x00404010, 0x20404000, 0x00000000, 0x20400010,
+ 0x00000010, 0x00004000, 0x20400000, 0x00404010,
+ 0x00004000, 0x00400010, 0x20004010, 0x00000000,
+ 0x20404000, 0x20000000, 0x00400010, 0x20004010
+};
+
+static const uint32_t SB7[64] =
+{
+ 0x00200000, 0x04200002, 0x04000802, 0x00000000,
+ 0x00000800, 0x04000802, 0x00200802, 0x04200800,
+ 0x04200802, 0x00200000, 0x00000000, 0x04000002,
+ 0x00000002, 0x04000000, 0x04200002, 0x00000802,
+ 0x04000800, 0x00200802, 0x00200002, 0x04000800,
+ 0x04000002, 0x04200000, 0x04200800, 0x00200002,
+ 0x04200000, 0x00000800, 0x00000802, 0x04200802,
+ 0x00200800, 0x00000002, 0x04000000, 0x00200800,
+ 0x04000000, 0x00200800, 0x00200000, 0x04000802,
+ 0x04000802, 0x04200002, 0x04200002, 0x00000002,
+ 0x00200002, 0x04000000, 0x04000800, 0x00200000,
+ 0x04200800, 0x00000802, 0x00200802, 0x04200800,
+ 0x00000802, 0x04000002, 0x04200802, 0x04200000,
+ 0x00200800, 0x00000000, 0x00000002, 0x04200802,
+ 0x00000000, 0x00200802, 0x04200000, 0x00000800,
+ 0x04000002, 0x04000800, 0x00000800, 0x00200002
+};
+
+static const uint32_t SB8[64] =
+{
+ 0x10001040, 0x00001000, 0x00040000, 0x10041040,
+ 0x10000000, 0x10001040, 0x00000040, 0x10000000,
+ 0x00040040, 0x10040000, 0x10041040, 0x00041000,
+ 0x10041000, 0x00041040, 0x00001000, 0x00000040,
+ 0x10040000, 0x10000040, 0x10001000, 0x00001040,
+ 0x00041000, 0x00040040, 0x10040040, 0x10041000,
+ 0x00001040, 0x00000000, 0x00000000, 0x10040040,
+ 0x10000040, 0x10001000, 0x00041040, 0x00040000,
+ 0x00041040, 0x00040000, 0x10041000, 0x00001000,
+ 0x00000040, 0x10040040, 0x00001000, 0x00041040,
+ 0x10001000, 0x00000040, 0x10000040, 0x10040000,
+ 0x10040040, 0x10000000, 0x00040000, 0x10001040,
+ 0x00000000, 0x10041040, 0x00040040, 0x10000040,
+ 0x10040000, 0x10001000, 0x10001040, 0x00000000,
+ 0x10041040, 0x00041000, 0x00041000, 0x00001040,
+ 0x00001040, 0x00040040, 0x10000000, 0x10041000
+};
+
+/*
+ * PC1: left and right halves bit-swap
+ */
+static const uint32_t LHs[16] =
+{
+ 0x00000000, 0x00000001, 0x00000100, 0x00000101,
+ 0x00010000, 0x00010001, 0x00010100, 0x00010101,
+ 0x01000000, 0x01000001, 0x01000100, 0x01000101,
+ 0x01010000, 0x01010001, 0x01010100, 0x01010101
+};
+
+static const uint32_t RHs[16] =
+{
+ 0x00000000, 0x01000000, 0x00010000, 0x01010000,
+ 0x00000100, 0x01000100, 0x00010100, 0x01010100,
+ 0x00000001, 0x01000001, 0x00010001, 0x01010001,
+ 0x00000101, 0x01000101, 0x00010101, 0x01010101,
+};
+
+/*
+ * Initial Permutation macro
+ */
+#define DES_IP(X,Y) \
+{ \
+ T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
+ T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
+ T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
+ T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
+ Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \
+ T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \
+ X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \
+}
+
+/*
+ * Final Permutation macro
+ */
+#define DES_FP(X,Y) \
+{ \
+ X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \
+ T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \
+ Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \
+ T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
+ T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
+ T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
+ T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
+}
+
+/*
+ * DES round macro
+ */
+#define DES_ROUND(X,Y) \
+{ \
+ T = *SK++ ^ X; \
+ Y ^= SB8[ (T ) & 0x3F ] ^ \
+ SB6[ (T >> 8) & 0x3F ] ^ \
+ SB4[ (T >> 16) & 0x3F ] ^ \
+ SB2[ (T >> 24) & 0x3F ]; \
+ \
+ T = *SK++ ^ ((X << 28) | (X >> 4)); \
+ Y ^= SB7[ (T ) & 0x3F ] ^ \
+ SB5[ (T >> 8) & 0x3F ] ^ \
+ SB3[ (T >> 16) & 0x3F ] ^ \
+ SB1[ (T >> 24) & 0x3F ]; \
+}
+
+#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; }
+
+static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8,
+ 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
+ 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
+ 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
+ 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
+ 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
+ 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
+ 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
+ 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
+ 254 };
+
+void des_key_set_parity( unsigned char key[DES_KEY_SIZE] )
+{
+ int i;
+
+ for( i = 0; i < DES_KEY_SIZE; i++ )
+ key[i] = odd_parity_table[key[i] / 2];
+}
+
+/*
+ * Check the given key's parity, returns 1 on failure, 0 on SUCCESS
+ */
+int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] )
+{
+ int i;
+
+ for( i = 0; i < DES_KEY_SIZE; i++ )
+ if ( key[i] != odd_parity_table[key[i] / 2] )
+ return( 1 );
+
+ return( 0 );
+}
+
+/*
+ * Table of weak and semi-weak keys
+ *
+ * Source: http://en.wikipedia.org/wiki/Weak_key
+ *
+ * Weak:
+ * Alternating ones + zeros (0x0101010101010101)
+ * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)
+ * '0xE0E0E0E0F1F1F1F1'
+ * '0x1F1F1F1F0E0E0E0E'
+ *
+ * Semi-weak:
+ * 0x011F011F010E010E and 0x1F011F010E010E01
+ * 0x01E001E001F101F1 and 0xE001E001F101F101
+ * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
+ * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
+ * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
+ * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
+ *
+ */
+
+#define WEAK_KEY_COUNT 16
+
+static const unsigned char weak_key_table[WEAK_KEY_COUNT][DES_KEY_SIZE] =
+{
+ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
+ { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
+ { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
+
+ { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
+ { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
+ { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
+ { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
+ { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
+ { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
+ { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
+ { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
+ { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
+ { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
+ { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
+ { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
+};
+
+int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] )
+{
+ int i;
+
+ for( i = 0; i < WEAK_KEY_COUNT; i++ )
+ if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0)
+ return( 1 );
+
+ return( 0 );
+}
+
+static void des_setkey( uint32_t SK[32], const unsigned char key[DES_KEY_SIZE] )
+{
+ int i;
+ uint32_t X, Y, T;
+
+ GET_UINT32_BE( X, key, 0 );
+ GET_UINT32_BE( Y, key, 4 );
+
+ /*
+ * Permuted Choice 1
+ */
+ T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4);
+ T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T );
+
+ X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2)
+ | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] )
+ | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
+ | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
+
+ Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2)
+ | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] )
+ | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
+ | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
+
+ X &= 0x0FFFFFFF;
+ Y &= 0x0FFFFFFF;
+
+ /*
+ * calculate subkeys
+ */
+ for( i = 0; i < 16; i++ )
+ {
+ if( i < 2 || i == 8 || i == 15 )
+ {
+ X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF;
+ Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF;
+ }
+ else
+ {
+ X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF;
+ Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF;
+ }
+
+ *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000)
+ | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
+ | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000)
+ | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000)
+ | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000)
+ | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000)
+ | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400)
+ | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100)
+ | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010)
+ | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004)
+ | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
+
+ *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
+ | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
+ | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000)
+ | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
+ | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000)
+ | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000)
+ | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000)
+ | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400)
+ | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100)
+ | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011)
+ | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002);
+ }
+}
+
+/*
+ * DES key schedule (56-bit, encryption)
+ */
+int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
+{
+ des_setkey( ctx->sk, key );
+
+ return( 0 );
+}
+
+/*
+ * DES key schedule (56-bit, decryption)
+ */
+int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
+{
+ int i;
+
+ des_setkey( ctx->sk, key );
+
+ for( i = 0; i < 16; i += 2 )
+ {
+ SWAP( ctx->sk[i ], ctx->sk[30 - i] );
+ SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
+ }
+
+ return( 0 );
+}
+
+static void des3_set2key( uint32_t esk[96],
+ uint32_t dsk[96],
+ const unsigned char key[DES_KEY_SIZE*2] )
+{
+ int i;
+
+ des_setkey( esk, key );
+ des_setkey( dsk + 32, key + 8 );
+
+ for( i = 0; i < 32; i += 2 )
+ {
+ dsk[i ] = esk[30 - i];
+ dsk[i + 1] = esk[31 - i];
+
+ esk[i + 32] = dsk[62 - i];
+ esk[i + 33] = dsk[63 - i];
+
+ esk[i + 64] = esk[i ];
+ esk[i + 65] = esk[i + 1];
+
+ dsk[i + 64] = dsk[i ];
+ dsk[i + 65] = dsk[i + 1];
+ }
+}
+
+/*
+ * Triple-DES key schedule (112-bit, encryption)
+ */
+int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] )
+{
+ uint32_t sk[96];
+
+ des3_set2key( ctx->sk, sk, key );
+ memset( sk, 0, sizeof( sk ) );
+
+ return( 0 );
+}
+
+/*
+ * Triple-DES key schedule (112-bit, decryption)
+ */
+int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] )
+{
+ uint32_t sk[96];
+
+ des3_set2key( sk, ctx->sk, key );
+ memset( sk, 0, sizeof( sk ) );
+
+ return( 0 );
+}
+
+static void des3_set3key( uint32_t esk[96],
+ uint32_t dsk[96],
+ const unsigned char key[24] )
+{
+ int i;
+
+ des_setkey( esk, key );
+ des_setkey( dsk + 32, key + 8 );
+ des_setkey( esk + 64, key + 16 );
+
+ for( i = 0; i < 32; i += 2 )
+ {
+ dsk[i ] = esk[94 - i];
+ dsk[i + 1] = esk[95 - i];
+
+ esk[i + 32] = dsk[62 - i];
+ esk[i + 33] = dsk[63 - i];
+
+ dsk[i + 64] = esk[30 - i];
+ dsk[i + 65] = esk[31 - i];
+ }
+}
+
+/*
+ * Triple-DES key schedule (168-bit, encryption)
+ */
+int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] )
+{
+ uint32_t sk[96];
+
+ des3_set3key( ctx->sk, sk, key );
+ memset( sk, 0, sizeof( sk ) );
+
+ return( 0 );
+}
+
+/*
+ * Triple-DES key schedule (168-bit, decryption)
+ */
+int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] )
+{
+ uint32_t sk[96];
+
+ des3_set3key( sk, ctx->sk, key );
+ memset( sk, 0, sizeof( sk ) );
+
+ return( 0 );
+}
+
+/*
+ * DES-ECB block encryption/decryption
+ */
+int des_crypt_ecb( des_context *ctx,
+ const unsigned char input[8],
+ unsigned char output[8] )
+{
+ int i;
+ uint32_t X, Y, T, *SK;
+
+ SK = ctx->sk;
+
+ GET_UINT32_BE( X, input, 0 );
+ GET_UINT32_BE( Y, input, 4 );
+
+ DES_IP( X, Y );
+
+ for( i = 0; i < 8; i++ )
+ {
+ DES_ROUND( Y, X );
+ DES_ROUND( X, Y );
+ }
+
+ DES_FP( Y, X );
+
+ PUT_UINT32_BE( Y, output, 0 );
+ PUT_UINT32_BE( X, output, 4 );
+
+ return( 0 );
+}
+
+/*
+ * DES-CBC buffer encryption/decryption
+ */
+int des_crypt_cbc( des_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[8];
+
+ if( length % 8 )
+ return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH );
+
+ if( mode == DES_ENCRYPT )
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ des_crypt_ecb( ctx, output, output );
+ memcpy( iv, output, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+ else /* DES_DECRYPT */
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 8 );
+ des_crypt_ecb( ctx, input, output );
+
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+
+ return( 0 );
+}
+
+/*
+ * 3DES-ECB block encryption/decryption
+ */
+int des3_crypt_ecb( des3_context *ctx,
+ const unsigned char input[8],
+ unsigned char output[8] )
+{
+ int i;
+ uint32_t X, Y, T, *SK;
+
+ SK = ctx->sk;
+
+ GET_UINT32_BE( X, input, 0 );
+ GET_UINT32_BE( Y, input, 4 );
+
+ DES_IP( X, Y );
+
+ for( i = 0; i < 8; i++ )
+ {
+ DES_ROUND( Y, X );
+ DES_ROUND( X, Y );
+ }
+
+ for( i = 0; i < 8; i++ )
+ {
+ DES_ROUND( X, Y );
+ DES_ROUND( Y, X );
+ }
+
+ for( i = 0; i < 8; i++ )
+ {
+ DES_ROUND( Y, X );
+ DES_ROUND( X, Y );
+ }
+
+ DES_FP( Y, X );
+
+ PUT_UINT32_BE( Y, output, 0 );
+ PUT_UINT32_BE( X, output, 4 );
+
+ return( 0 );
+}
+
+/*
+ * 3DES-CBC buffer encryption/decryption
+ */
+int des3_crypt_cbc( des3_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[8];
+
+ if( length % 8 )
+ return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH );
+
+ if( mode == DES_ENCRYPT )
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ des3_crypt_ecb( ctx, output, output );
+ memcpy( iv, output, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+ else /* DES_DECRYPT */
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 8 );
+ des3_crypt_ecb( ctx, input, output );
+
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+
+ return( 0 );
+}
+
+#endif /* !POLARSSL_DES_ALT */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include
+
+/*
+ * DES and 3DES test vectors from:
+ *
+ * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip
+ */
+static const unsigned char des3_test_keys[24] =
+{
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+ 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
+ 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
+};
+
+static const unsigned char des3_test_iv[8] =
+{
+ 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,
+};
+
+static const unsigned char des3_test_buf[8] =
+{
+ 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74
+};
+
+static const unsigned char des3_test_ecb_dec[3][8] =
+{
+ { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D },
+ { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB },
+ { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A }
+};
+
+static const unsigned char des3_test_ecb_enc[3][8] =
+{
+ { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B },
+ { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 },
+ { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 }
+};
+
+static const unsigned char des3_test_cbc_dec[3][8] =
+{
+ { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 },
+ { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 },
+ { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C }
+};
+
+static const unsigned char des3_test_cbc_enc[3][8] =
+{
+ { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 },
+ { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D },
+ { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 }
+};
+
+/*
+ * Checkup routine
+ */
+int des_self_test( int verbose )
+{
+ int i, j, u, v;
+ des_context ctx;
+ des3_context ctx3;
+ unsigned char key[24];
+ unsigned char buf[8];
+ unsigned char prv[8];
+ unsigned char iv[8];
+
+ memset( key, 0, 24 );
+
+ /*
+ * ECB mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " DES%c-ECB-%3d (%s): ",
+ ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+ ( v == DES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( buf, des3_test_buf, 8 );
+
+ switch( i )
+ {
+ case 0:
+ des_setkey_dec( &ctx, des3_test_keys );
+ break;
+
+ case 1:
+ des_setkey_enc( &ctx, des3_test_keys );
+ break;
+
+ case 2:
+ des3_set2key_dec( &ctx3, des3_test_keys );
+ break;
+
+ case 3:
+ des3_set2key_enc( &ctx3, des3_test_keys );
+ break;
+
+ case 4:
+ des3_set3key_dec( &ctx3, des3_test_keys );
+ break;
+
+ case 5:
+ des3_set3key_enc( &ctx3, des3_test_keys );
+ break;
+
+ default:
+ return( 1 );
+ }
+
+ for( j = 0; j < 10000; j++ )
+ {
+ if( u == 0 )
+ des_crypt_ecb( &ctx, buf, buf );
+ else
+ des3_crypt_ecb( &ctx3, buf, buf );
+ }
+
+ if( ( v == DES_DECRYPT &&
+ memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) ||
+ ( v != DES_DECRYPT &&
+ memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ /*
+ * CBC mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " DES%c-CBC-%3d (%s): ",
+ ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+ ( v == DES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( iv, des3_test_iv, 8 );
+ memcpy( prv, des3_test_iv, 8 );
+ memcpy( buf, des3_test_buf, 8 );
+
+ switch( i )
+ {
+ case 0:
+ des_setkey_dec( &ctx, des3_test_keys );
+ break;
+
+ case 1:
+ des_setkey_enc( &ctx, des3_test_keys );
+ break;
+
+ case 2:
+ des3_set2key_dec( &ctx3, des3_test_keys );
+ break;
+
+ case 3:
+ des3_set2key_enc( &ctx3, des3_test_keys );
+ break;
+
+ case 4:
+ des3_set3key_dec( &ctx3, des3_test_keys );
+ break;
+
+ case 5:
+ des3_set3key_enc( &ctx3, des3_test_keys );
+ break;
+
+ default:
+ return( 1 );
+ }
+
+ if( v == DES_DECRYPT )
+ {
+ for( j = 0; j < 10000; j++ )
+ {
+ if( u == 0 )
+ des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+ else
+ des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+ }
+ }
+ else
+ {
+ for( j = 0; j < 10000; j++ )
+ {
+ unsigned char tmp[8];
+
+ if( u == 0 )
+ des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+ else
+ des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+
+ memcpy( tmp, prv, 8 );
+ memcpy( prv, buf, 8 );
+ memcpy( buf, tmp, 8 );
+ }
+
+ memcpy( buf, prv, 8 );
+ }
+
+ if( ( v == DES_DECRYPT &&
+ memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) ||
+ ( v != DES_DECRYPT &&
+ memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/des.h b/polarssl/des.h
new file mode 100644
index 0000000..443cd3f
--- /dev/null
+++ b/polarssl/des.h
@@ -0,0 +1,252 @@
+/**
+ * \file des.h
+ *
+ * \brief DES block cipher
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_DES_H
+#define POLARSSL_DES_H
+
+#include "polarssl/config.h"
+
+#include
+
+#ifdef _MSC_VER
+#include
+typedef UINT32 uint32_t;
+#else
+#include
+#endif
+
+#define DES_ENCRYPT 1
+#define DES_DECRYPT 0
+
+#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */
+
+#define DES_KEY_SIZE 8
+
+#if !defined(POLARSSL_DES_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief DES context structure
+ */
+typedef struct
+{
+ int mode; /*!< encrypt/decrypt */
+ uint32_t sk[32]; /*!< DES subkeys */
+}
+des_context;
+
+/**
+ * \brief Triple-DES context structure
+ */
+typedef struct
+{
+ int mode; /*!< encrypt/decrypt */
+ uint32_t sk[96]; /*!< 3DES subkeys */
+}
+des3_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Set key parity on the given key to odd.
+ *
+ * DES keys are 56 bits long, but each byte is padded with
+ * a parity bit to allow verification.
+ *
+ * \param key 8-byte secret key
+ */
+void des_key_set_parity( unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief Check that key parity on the given key is odd.
+ *
+ * DES keys are 56 bits long, but each byte is padded with
+ * a parity bit to allow verification.
+ *
+ * \param key 8-byte secret key
+ *
+ * \return 0 is parity was ok, 1 if parity was not correct.
+ */
+int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief Check that key is not a weak or semi-weak DES key
+ *
+ * \param key 8-byte secret key
+ *
+ * \return 0 if no weak key was found, 1 if a weak key was identified.
+ */
+int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief DES key schedule (56-bit, encryption)
+ *
+ * \param ctx DES context to be initialized
+ * \param key 8-byte secret key
+ *
+ * \return 0
+ */
+int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief DES key schedule (56-bit, decryption)
+ *
+ * \param ctx DES context to be initialized
+ * \param key 8-byte secret key
+ *
+ * \return 0
+ */
+int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief Triple-DES key schedule (112-bit, encryption)
+ *
+ * \param ctx 3DES context to be initialized
+ * \param key 16-byte secret key
+ *
+ * \return 0
+ */
+int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] );
+
+/**
+ * \brief Triple-DES key schedule (112-bit, decryption)
+ *
+ * \param ctx 3DES context to be initialized
+ * \param key 16-byte secret key
+ *
+ * \return 0
+ */
+int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] );
+
+/**
+ * \brief Triple-DES key schedule (168-bit, encryption)
+ *
+ * \param ctx 3DES context to be initialized
+ * \param key 24-byte secret key
+ *
+ * \return 0
+ */
+int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] );
+
+/**
+ * \brief Triple-DES key schedule (168-bit, decryption)
+ *
+ * \param ctx 3DES context to be initialized
+ * \param key 24-byte secret key
+ *
+ * \return 0
+ */
+int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] );
+
+/**
+ * \brief DES-ECB block encryption/decryption
+ *
+ * \param ctx DES context
+ * \param input 64-bit input block
+ * \param output 64-bit output block
+ *
+ * \return 0 if successful
+ */
+int des_crypt_ecb( des_context *ctx,
+ const unsigned char input[8],
+ unsigned char output[8] );
+
+/**
+ * \brief DES-CBC buffer encryption/decryption
+ *
+ * \param ctx DES context
+ * \param mode DES_ENCRYPT or DES_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ */
+int des_crypt_cbc( des_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief 3DES-ECB block encryption/decryption
+ *
+ * \param ctx 3DES context
+ * \param input 64-bit input block
+ * \param output 64-bit output block
+ *
+ * \return 0 if successful
+ */
+int des3_crypt_ecb( des3_context *ctx,
+ const unsigned char input[8],
+ unsigned char output[8] );
+
+/**
+ * \brief 3DES-CBC buffer encryption/decryption
+ *
+ * \param ctx 3DES context
+ * \param mode DES_ENCRYPT or DES_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or POLARSSL_ERR_DES_INVALID_INPUT_LENGTH
+ */
+int des3_crypt_cbc( des3_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ const unsigned char *input,
+ unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* POLARSSL_DES_ALT */
+#include "polarssl/des_alt.h"
+#endif /* POLARSSL_DES_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int des_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* des.h */
diff --git a/polarssl/dhm.c b/polarssl/dhm.c
new file mode 100644
index 0000000..90e5b4b
--- /dev/null
+++ b/polarssl/dhm.c
@@ -0,0 +1,302 @@
+/*
+ * Diffie-Hellman-Merkle key exchange
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * Reference:
+ *
+ * http://www.cacr.math.uwaterloo.ca/hac/ (chapter 12)
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_DHM_C)
+
+#include "polarssl/dhm.h"
+
+/*
+ * helper to validate the mpi size and import it
+ */
+static int dhm_read_bignum( mpi *X,
+ unsigned char **p,
+ const unsigned char *end )
+{
+ int ret, n;
+
+ if( end - *p < 2 )
+ return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+ n = ( (*p)[0] << 8 ) | (*p)[1];
+ (*p) += 2;
+
+ if( (int)( end - *p ) < n )
+ return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+ if( ( ret = mpi_read_binary( X, *p, n ) ) != 0 )
+ return( POLARSSL_ERR_DHM_READ_PARAMS_FAILED + ret );
+
+ (*p) += n;
+
+ return( 0 );
+}
+
+/*
+ * Verify sanity of parameter with regards to P
+ *
+ * Parameter should be: 2 <= public_param <= P - 2
+ *
+ * For more information on the attack, see:
+ * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
+ * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
+ */
+static int dhm_check_range( const mpi *param, const mpi *P )
+{
+ mpi L, U;
+ int ret = POLARSSL_ERR_DHM_BAD_INPUT_DATA;
+
+ mpi_init( &L ); mpi_init( &U );
+ mpi_lset( &L, 2 );
+ mpi_sub_int( &U, P, 2 );
+
+ if( mpi_cmp_mpi( param, &L ) >= 0 &&
+ mpi_cmp_mpi( param, &U ) <= 0 )
+ {
+ ret = 0;
+ }
+
+ mpi_free( &L ); mpi_free( &U );
+
+ return( ret );
+}
+
+/*
+ * Parse the ServerKeyExchange parameters
+ */
+int dhm_read_params( dhm_context *ctx,
+ unsigned char **p,
+ const unsigned char *end )
+{
+ int ret;
+
+ memset( ctx, 0, sizeof( dhm_context ) );
+
+ if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
+ ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
+ ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
+ return( ret );
+
+ if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
+ return( ret );
+
+ ctx->len = mpi_size( &ctx->P );
+
+ if( end - *p < 2 )
+ return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+ return( 0 );
+}
+
+/*
+ * Setup and write the ServerKeyExchange parameters
+ */
+int dhm_make_params( dhm_context *ctx, int x_size,
+ unsigned char *output, size_t *olen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret, count = 0;
+ size_t n1, n2, n3;
+ unsigned char *p;
+
+ if( mpi_cmp_int( &ctx->P, 0 ) == 0 )
+ return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+ /*
+ * Generate X as large as possible ( < P )
+ */
+ do
+ {
+ mpi_fill_random( &ctx->X, x_size, f_rng, p_rng );
+
+ while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
+ mpi_shift_r( &ctx->X, 1 );
+
+ if( count++ > 10 )
+ return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED );
+ }
+ while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
+
+ /*
+ * Calculate GX = G^X mod P
+ */
+ MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
+ &ctx->P , &ctx->RP ) );
+
+ if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
+ return( ret );
+
+ /*
+ * export P, G, GX
+ */
+#define DHM_MPI_EXPORT(X,n) \
+ MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \
+ *p++ = (unsigned char)( n >> 8 ); \
+ *p++ = (unsigned char)( n ); p += n;
+
+ n1 = mpi_size( &ctx->P );
+ n2 = mpi_size( &ctx->G );
+ n3 = mpi_size( &ctx->GX );
+
+ p = output;
+ DHM_MPI_EXPORT( &ctx->P , n1 );
+ DHM_MPI_EXPORT( &ctx->G , n2 );
+ DHM_MPI_EXPORT( &ctx->GX, n3 );
+
+ *olen = p - output;
+
+ ctx->len = n1;
+
+cleanup:
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED + ret );
+
+ return( 0 );
+}
+
+/*
+ * Import the peer's public value G^Y
+ */
+int dhm_read_public( dhm_context *ctx,
+ const unsigned char *input, size_t ilen )
+{
+ int ret;
+
+ if( ctx == NULL || ilen < 1 || ilen > ctx->len )
+ return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+ if( ( ret = mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
+ return( POLARSSL_ERR_DHM_READ_PUBLIC_FAILED + ret );
+
+ return( 0 );
+}
+
+/*
+ * Create own private value X and export G^X
+ */
+int dhm_make_public( dhm_context *ctx, int x_size,
+ unsigned char *output, size_t olen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret, count = 0;
+
+ if( ctx == NULL || olen < 1 || olen > ctx->len )
+ return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+ if( mpi_cmp_int( &ctx->P, 0 ) == 0 )
+ return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+ /*
+ * generate X and calculate GX = G^X mod P
+ */
+ do
+ {
+ mpi_fill_random( &ctx->X, x_size, f_rng, p_rng );
+
+ while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
+ mpi_shift_r( &ctx->X, 1 );
+
+ if( count++ > 10 )
+ return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED );
+ }
+ while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
+
+ MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
+ &ctx->P , &ctx->RP ) );
+
+ if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
+ return( ret );
+
+ MPI_CHK( mpi_write_binary( &ctx->GX, output, olen ) );
+
+cleanup:
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
+
+ return( 0 );
+}
+
+/*
+ * Derive and export the shared secret (G^Y)^X mod P
+ */
+int dhm_calc_secret( dhm_context *ctx,
+ unsigned char *output, size_t *olen )
+{
+ int ret;
+
+ if( ctx == NULL || *olen < ctx->len )
+ return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+ MPI_CHK( mpi_exp_mod( &ctx->K, &ctx->GY, &ctx->X,
+ &ctx->P, &ctx->RP ) );
+
+ if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
+ return( ret );
+
+ *olen = mpi_size( &ctx->K );
+
+ MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) );
+
+cleanup:
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_DHM_CALC_SECRET_FAILED + ret );
+
+ return( 0 );
+}
+
+/*
+ * Free the components of a DHM key
+ */
+void dhm_free( dhm_context *ctx )
+{
+ mpi_free( &ctx->RP ); mpi_free( &ctx->K ); mpi_free( &ctx->GY );
+ mpi_free( &ctx->GX ); mpi_free( &ctx->X ); mpi_free( &ctx->G );
+ mpi_free( &ctx->P );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * Checkup routine
+ */
+int dhm_self_test( int verbose )
+{
+ return( verbose++ );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/dhm.h b/polarssl/dhm.h
new file mode 100644
index 0000000..a1643ca
--- /dev/null
+++ b/polarssl/dhm.h
@@ -0,0 +1,244 @@
+/**
+ * \file dhm.h
+ *
+ * \brief Diffie-Hellman-Merkle key exchange
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_DHM_H
+#define POLARSSL_DHM_H
+
+#include "polarssl/bignum.h"
+
+/*
+ * DHM Error codes
+ */
+#define POLARSSL_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED -0x3100 /**< Reading of the DHM parameters failed. */
+#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /**< Making of the DHM parameters failed. */
+#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /**< Reading of the public values failed. */
+#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /**< Making of the public value failed. */
+#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED -0x3300 /**< Calculation of the DHM secret failed. */
+
+/**
+ * RFC 3526 defines a number of standardized Diffie-Hellman groups
+ * for IKE.
+ * RFC 5114 defines a number of standardized Diffie-Hellman groups
+ * that can be used.
+ *
+ * Some are included here for convenience.
+ *
+ * Included are:
+ * RFC 3526 3. 2048-bit MODP Group
+ * RFC 3526 4. 3072-bit MODP Group
+ * RFC 5114 2.1. 1024-bit MODP Group with 160-bit Prime Order Subgroup
+ * RFC 5114 2.2. 2048-bit MODP Group with 224-bit Prime Order Subgroup
+ */
+#define POLARSSL_DHM_RFC3526_MODP_2048_P \
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \
+ "15728E5A8AACAA68FFFFFFFFFFFFFFFF"
+
+#define POLARSSL_DHM_RFC3526_MODP_2048_G "02"
+
+#define POLARSSL_DHM_RFC3526_MODP_3072_P \
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \
+ "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \
+ "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \
+ "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \
+ "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \
+ "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF"
+
+#define POLARSSL_DHM_RFC3526_MODP_3072_G "02"
+
+#define POLARSSL_DHM_RFC5114_MODP_1024_P \
+ "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6" \
+ "9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0" \
+ "13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70" \
+ "98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0" \
+ "A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708" \
+ "DF1FB2BC2E4A4371"
+
+#define POLARSSL_DHM_RFC5114_MODP_1024_G \
+ "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F" \
+ "D6406CFF14266D31266FEA1E5C41564B777E690F5504F213" \
+ "160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1" \
+ "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A" \
+ "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24" \
+ "855E6EEB22B3B2E5"
+
+#define POLARSSL_DHM_RFC5114_MODP_2048_P \
+ "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \
+ "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \
+ "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \
+ "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \
+ "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \
+ "B3BF8A317091883681286130BC8985DB1602E714415D9330" \
+ "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \
+ "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \
+ "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \
+ "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \
+ "CF9DE5384E71B81C0AC4DFFE0C10E64F"
+
+#define POLARSSL_DHM_RFC5114_MODP_2048_G \
+ "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF"\
+ "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA"\
+ "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7"\
+ "C17669101999024AF4D027275AC1348BB8A762D0521BC98A"\
+ "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE"\
+ "F180EB34118E98D119529A45D6F834566E3025E316A330EF"\
+ "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB"\
+ "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381"\
+ "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269"\
+ "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179"\
+ "81BC087F2A7065B384B890D3191F2BFA"
+
+/**
+ * \brief DHM context structure
+ */
+typedef struct
+{
+ size_t len; /*!< size(P) in chars */
+ mpi P; /*!< prime modulus */
+ mpi G; /*!< generator */
+ mpi X; /*!< secret value */
+ mpi GX; /*!< self = G^X mod P */
+ mpi GY; /*!< peer = G^Y mod P */
+ mpi K; /*!< key = GY^X mod P */
+ mpi RP; /*!< cached R^2 mod P */
+}
+dhm_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Parse the ServerKeyExchange parameters
+ *
+ * \param ctx DHM context
+ * \param p &(start of input buffer)
+ * \param end end of buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_read_params( dhm_context *ctx,
+ unsigned char **p,
+ const unsigned char *end );
+
+/**
+ * \brief Setup and write the ServerKeyExchange parameters
+ *
+ * \param ctx DHM context
+ * \param x_size private value size in bytes
+ * \param output destination buffer
+ * \param olen number of chars written
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \note This function assumes that ctx->P and ctx->G
+ * have already been properly set (for example
+ * using mpi_read_string or mpi_read_binary).
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_make_params( dhm_context *ctx, int x_size,
+ unsigned char *output, size_t *olen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Import the peer's public value G^Y
+ *
+ * \param ctx DHM context
+ * \param input input buffer
+ * \param ilen size of buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_read_public( dhm_context *ctx,
+ const unsigned char *input, size_t ilen );
+
+/**
+ * \brief Create own private value X and export G^X
+ *
+ * \param ctx DHM context
+ * \param x_size private value size in bytes
+ * \param output destination buffer
+ * \param olen must be equal to ctx->P.len
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_make_public( dhm_context *ctx, int x_size,
+ unsigned char *output, size_t olen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Derive and export the shared secret (G^Y)^X mod P
+ *
+ * \param ctx DHM context
+ * \param output destination buffer
+ * \param olen number of chars written
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_calc_secret( dhm_context *ctx,
+ unsigned char *output, size_t *olen );
+
+/**
+ * \brief Free the components of a DHM key
+ */
+void dhm_free( dhm_context *ctx );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int dhm_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/polarssl/entropy.c b/polarssl/entropy.c
new file mode 100644
index 0000000..9662454
--- /dev/null
+++ b/polarssl/entropy.c
@@ -0,0 +1,204 @@
+/*
+ * Entropy accumulator implementation
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_ENTROPY_C)
+
+#include "polarssl/entropy.h"
+#include "polarssl/entropy_poll.h"
+
+#if defined(POLARSSL_HAVEGE_C)
+#include "polarssl/havege.h"
+#endif
+
+#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
+
+void entropy_init( entropy_context *ctx )
+{
+ memset( ctx, 0, sizeof(entropy_context) );
+
+ sha4_starts( &ctx->accumulator, 0 );
+#if defined(POLARSSL_HAVEGE_C)
+ havege_init( &ctx->havege_data );
+#endif
+
+#if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
+#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
+ entropy_add_source( ctx, platform_entropy_poll, NULL,
+ ENTROPY_MIN_PLATFORM );
+#endif
+#if defined(POLARSSL_TIMING_C)
+ entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK );
+#endif
+#if defined(POLARSSL_HAVEGE_C)
+ entropy_add_source( ctx, havege_poll, &ctx->havege_data,
+ ENTROPY_MIN_HAVEGE );
+#endif
+#endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
+}
+
+int entropy_add_source( entropy_context *ctx,
+ f_source_ptr f_source, void *p_source,
+ size_t threshold )
+{
+ int index = ctx->source_count;
+
+ if( index >= ENTROPY_MAX_SOURCES )
+ return( POLARSSL_ERR_ENTROPY_MAX_SOURCES );
+
+ ctx->source[index].f_source = f_source;
+ ctx->source[index].p_source = p_source;
+ ctx->source[index].threshold = threshold;
+
+ ctx->source_count++;
+
+ return( 0 );
+}
+
+/*
+ * Entropy accumulator update
+ */
+int entropy_update( entropy_context *ctx, unsigned char source_id,
+ const unsigned char *data, size_t len )
+{
+ unsigned char header[2];
+ unsigned char tmp[ENTROPY_BLOCK_SIZE];
+ size_t use_len = len;
+ const unsigned char *p = data;
+
+ if( use_len > ENTROPY_BLOCK_SIZE )
+ {
+ sha4( data, len, tmp, 0 );
+
+ p = tmp;
+ use_len = ENTROPY_BLOCK_SIZE;
+ }
+
+ header[0] = source_id;
+ header[1] = use_len & 0xFF;
+
+ sha4_update( &ctx->accumulator, header, 2 );
+ sha4_update( &ctx->accumulator, p, use_len );
+
+ return( 0 );
+}
+
+int entropy_update_manual( entropy_context *ctx,
+ const unsigned char *data, size_t len )
+{
+ return entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
+}
+
+/*
+ * Run through the different sources to add entropy to our accumulator
+ */
+int entropy_gather( entropy_context *ctx )
+{
+ int ret, i;
+ unsigned char buf[ENTROPY_MAX_GATHER];
+ size_t olen;
+
+ if( ctx->source_count == 0 )
+ return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED );
+
+ /*
+ * Run through our entropy sources
+ */
+ for( i = 0; i < ctx->source_count; i++ )
+ {
+ olen = 0;
+ if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
+ buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ /*
+ * Add if we actually gathered something
+ */
+ if( olen > 0 )
+ {
+ entropy_update( ctx, (unsigned char) i, buf, olen );
+ ctx->source[i].size += olen;
+ }
+ }
+
+ return( 0 );
+}
+
+int entropy_func( void *data, unsigned char *output, size_t len )
+{
+ int ret, count = 0, i, reached;
+ entropy_context *ctx = (entropy_context *) data;
+ unsigned char buf[ENTROPY_BLOCK_SIZE];
+
+ if( len > ENTROPY_BLOCK_SIZE )
+ return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
+
+ /*
+ * Always gather extra entropy before a call
+ */
+ do
+ {
+ if( count++ > ENTROPY_MAX_LOOP )
+ return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
+
+ if( ( ret = entropy_gather( ctx ) ) != 0 )
+ return( ret );
+
+ reached = 0;
+
+ for( i = 0; i < ctx->source_count; i++ )
+ if( ctx->source[i].size >= ctx->source[i].threshold )
+ reached++;
+ }
+ while( reached != ctx->source_count );
+
+ memset( buf, 0, ENTROPY_BLOCK_SIZE );
+
+ sha4_finish( &ctx->accumulator, buf );
+
+ /*
+ * Perform second SHA-512 on entropy
+ */
+ sha4( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
+
+ /*
+ * Reset accumulator and counters and recycle existing entropy
+ */
+ memset( &ctx->accumulator, 0, sizeof( sha4_context ) );
+ sha4_starts( &ctx->accumulator, 0 );
+ sha4_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
+
+ for( i = 0; i < ctx->source_count; i++ )
+ ctx->source[i].size = 0;
+
+ memcpy( output, buf, len );
+
+ return( 0 );
+}
+
+#endif
diff --git a/polarssl/entropy.h b/polarssl/entropy.h
new file mode 100644
index 0000000..5b6b380
--- /dev/null
+++ b/polarssl/entropy.h
@@ -0,0 +1,153 @@
+/**
+ * \file entropy.h
+ *
+ * \brief Entropy accumulator implementation
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ENTROPY_H
+#define POLARSSL_ENTROPY_H
+
+#include
+
+#include "polarssl/config.h"
+
+#include "polarssl/sha4.h"
+#if defined(POLARSSL_HAVEGE_C)
+#include "polarssl/havege.h"
+#endif
+
+#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */
+#define POLARSSL_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */
+#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */
+
+#if !defined(POLARSSL_CONFIG_OPTIONS)
+#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */
+#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */
+#endif /* !POLARSSL_CONFIG_OPTIONS */
+
+#define ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */
+
+#define ENTROPY_SOURCE_MANUAL ENTROPY_MAX_SOURCES
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Entropy poll callback pointer
+ *
+ * \param data Callback-specific data pointer
+ * \param output Data to fill
+ * \param len Maximum size to provide
+ * \param olen The actual amount of bytes put into the buffer (Can be 0)
+ *
+ * \return 0 if no critical failures occurred,
+ * POLARSSL_ERR_ENTROPY_SOURCE_FAILED otherwise
+ */
+typedef int (*f_source_ptr)(void *, unsigned char *, size_t, size_t *);
+
+/**
+ * \brief Entropy source state
+ */
+typedef struct
+{
+ f_source_ptr f_source; /**< The entropy source callback */
+ void * p_source; /**< The callback data pointer */
+ size_t size; /**< Amount received */
+ size_t threshold; /**< Minimum level required before release */
+}
+source_state;
+
+/**
+ * \brief Entropy context structure
+ */
+typedef struct
+{
+ sha4_context accumulator;
+ int source_count;
+ source_state source[ENTROPY_MAX_SOURCES];
+#if defined(POLARSSL_HAVEGE_C)
+ havege_state havege_data;
+#endif
+}
+entropy_context;
+
+/**
+ * \brief Initialize the context
+ *
+ * \param ctx Entropy context to initialize
+ */
+void entropy_init( entropy_context *ctx );
+
+/**
+ * \brief Adds an entropy source to poll
+ *
+ * \param ctx Entropy context
+ * \param f_source Entropy function
+ * \param p_source Function data
+ * \param threshold Minimum required from source before entropy is released
+ * ( with entropy_func() )
+ *
+ * \return 0 if successful or POLARSSL_ERR_ENTROPY_MAX_SOURCES
+ */
+int entropy_add_source( entropy_context *ctx,
+ f_source_ptr f_source, void *p_source,
+ size_t threshold );
+
+/**
+ * \brief Trigger an extra gather poll for the accumulator
+ *
+ * \param ctx Entropy context
+ *
+ * \return 0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED
+ */
+int entropy_gather( entropy_context *ctx );
+
+/**
+ * \brief Retrieve entropy from the accumulator (Max ENTROPY_BLOCK_SIZE)
+ *
+ * \param data Entropy context
+ * \param output Buffer to fill
+ * \param len Length of buffer
+ *
+ * \return 0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED
+ */
+int entropy_func( void *data, unsigned char *output, size_t len );
+
+/**
+ * \brief Add data to the accumulator manually
+ *
+ * \param ctx Entropy context
+ * \param data Data to add
+ * \param len Length of data
+ *
+ * \return 0 if successful
+ */
+int entropy_update_manual( entropy_context *ctx,
+ const unsigned char *data, size_t len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* entropy.h */
diff --git a/polarssl/entropy_poll.c b/polarssl/entropy_poll.c
new file mode 100644
index 0000000..b5d9f78
--- /dev/null
+++ b/polarssl/entropy_poll.c
@@ -0,0 +1,136 @@
+/*
+ * Platform-specific and custom entropy polling functions
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_ENTROPY_C)
+
+#include "polarssl/entropy.h"
+#include "polarssl/entropy_poll.h"
+
+#if defined(POLARSSL_TIMING_C)
+#include "polarssl/timing.h"
+#endif
+#if defined(POLARSSL_HAVEGE_C)
+#include "polarssl/havege.h"
+#endif
+
+#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
+#if defined(_WIN32)
+
+#if !defined(_WIN32_WINNT)
+#define _WIN32_WINNT 0x0400
+#endif
+#include
+#include
+
+int platform_entropy_poll( void *data, unsigned char *output, size_t len,
+ size_t *olen )
+{
+ HCRYPTPROV provider;
+ ((void) data);
+ *olen = 0;
+
+ if( CryptAcquireContext( &provider, NULL, NULL,
+ PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )
+ {
+ return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+ }
+
+ if( CryptGenRandom( provider, len, output ) == FALSE )
+ return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+
+ CryptReleaseContext( provider, 0 );
+ *olen = len;
+
+ return( 0 );
+}
+#else
+
+#include
+
+int platform_entropy_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen )
+{
+ FILE *file;
+ size_t ret;
+ ((void) data);
+
+ *olen = 0;
+
+ file = fopen( "/dev/urandom", "rb" );
+ if( file == NULL )
+ return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+
+ ret = fread( output, 1, len, file );
+ if( ret != len )
+ {
+ fclose( file );
+ return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+ }
+
+ fclose( file );
+ *olen = len;
+
+ return( 0 );
+}
+#endif
+#endif
+
+#if defined(POLARSSL_TIMING_C)
+int hardclock_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen )
+{
+ unsigned long timer = hardclock();
+ ((void) data);
+ *olen = 0;
+
+ if( len < sizeof(unsigned long) )
+ return( 0 );
+
+ memcpy( output, &timer, sizeof(unsigned long) );
+ *olen = sizeof(unsigned long);
+
+ return( 0 );
+}
+#endif
+
+#if defined(POLARSSL_HAVEGE_C)
+int havege_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen )
+{
+ havege_state *hs = (havege_state *) data;
+ *olen = 0;
+
+ if( havege_random( hs, output, len ) != 0 )
+ return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+
+ *olen = len;
+
+ return( 0 );
+}
+#endif
+
+#endif /* POLARSSL_ENTROPY_C */
diff --git a/polarssl/entropy_poll.h b/polarssl/entropy_poll.h
new file mode 100644
index 0000000..4d09e74
--- /dev/null
+++ b/polarssl/entropy_poll.h
@@ -0,0 +1,75 @@
+/**
+ * \file entropy_poll.h
+ *
+ * \brief Platform-specific and custom entropy polling functions
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ENTROPY_POLL_H
+#define POLARSSL_ENTROPY_POLL_H
+
+#include
+
+#include "polarssl/config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Default thresholds for built-in sources
+ */
+#define ENTROPY_MIN_PLATFORM 128 /**< Minimum for platform source */
+#define ENTROPY_MIN_HAVEGE 128 /**< Minimum for HAVEGE */
+#define ENTROPY_MIN_HARDCLOCK 32 /**< Minimum for hardclock() */
+
+#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
+/**
+ * \brief Platform-specific entropy poll callback
+ */
+int platform_entropy_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if defined(POLARSSL_HAVEGE_C)
+/**
+ * \brief HAVEGE based entropy poll callback
+ *
+ * Requires an HAVEGE state as its data pointer.
+ */
+int havege_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if defined(POLARSSL_TIMING_C)
+/**
+ * \brief hardclock-based entropy poll callback
+ */
+int hardclock_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* entropy_poll.h */
diff --git a/polarssl/error.c b/polarssl/error.c
new file mode 100644
index 0000000..036b834
--- /dev/null
+++ b/polarssl/error.c
@@ -0,0 +1,612 @@
+/*
+ * Error message information
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_ERROR_C)
+
+#include "polarssl/error.h"
+
+#if defined(POLARSSL_AES_C)
+#include "polarssl/aes.h"
+#endif
+
+#if defined(POLARSSL_BASE64_C)
+#include "polarssl/base64.h"
+#endif
+
+#if defined(POLARSSL_BIGNUM_C)
+#include "polarssl/bignum.h"
+#endif
+
+#if defined(POLARSSL_BLOWFISH_C)
+#include "polarssl/blowfish.h"
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+#include "polarssl/camellia.h"
+#endif
+
+#if defined(POLARSSL_CIPHER_C)
+#include "polarssl/cipher.h"
+#endif
+
+#if defined(POLARSSL_CTR_DRBG_C)
+#include "polarssl/ctr_drbg.h"
+#endif
+
+#if defined(POLARSSL_DES_C)
+#include "polarssl/des.h"
+#endif
+
+#if defined(POLARSSL_DHM_C)
+#include "polarssl/dhm.h"
+#endif
+
+#if defined(POLARSSL_ENTROPY_C)
+#include "polarssl/entropy.h"
+#endif
+
+#if defined(POLARSSL_GCM_C)
+#include "polarssl/gcm.h"
+#endif
+
+#if defined(POLARSSL_MD_C)
+#include "polarssl/md.h"
+#endif
+
+#if defined(POLARSSL_MD2_C)
+#include "polarssl/md2.h"
+#endif
+
+#if defined(POLARSSL_MD4_C)
+#include "polarssl/md4.h"
+#endif
+
+#if defined(POLARSSL_MD5_C)
+#include "polarssl/md5.h"
+#endif
+
+#if defined(POLARSSL_NET_C)
+#include "polarssl/net.h"
+#endif
+
+#if defined(POLARSSL_PADLOCK_C)
+#include "polarssl/padlock.h"
+#endif
+
+#if defined(POLARSSL_PBKDF2_C)
+#include "polarssl/pbkdf2.h"
+#endif
+
+#if defined(POLARSSL_PEM_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_PKCS12_C)
+#include "polarssl/pkcs12.h"
+#endif
+
+#if defined(POLARSSL_PKCS5_C)
+#include "polarssl/pkcs5.h"
+#endif
+
+#if defined(POLARSSL_RSA_C)
+#include "polarssl/rsa.h"
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+#include "polarssl/sha1.h"
+#endif
+
+#if defined(POLARSSL_SHA2_C)
+#include "polarssl/sha2.h"
+#endif
+
+#if defined(POLARSSL_SHA4_C)
+#include "polarssl/sha4.h"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C)
+#include "polarssl/ssl.h"
+#endif
+
+#if defined(POLARSSL_X509_PARSE_C)
+#include "polarssl/x509.h"
+#endif
+
+#if defined(POLARSSL_XTEA_C)
+#include "polarssl/xtea.h"
+#endif
+
+
+#include
+
+#if defined _MSC_VER && !defined snprintf
+#define snprintf _snprintf
+#endif
+
+void error_strerror( int ret, char *buf, size_t buflen )
+{
+ size_t len;
+ int use_ret;
+
+ memset( buf, 0x00, buflen );
+
+ if( ret < 0 )
+ ret = -ret;
+
+ if( ret & 0xFF80 )
+ {
+ use_ret = ret & 0xFF80;
+
+ // High level error codes
+ //
+#if defined(POLARSSL_CIPHER_C)
+ if( use_ret == -(POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE) )
+ snprintf( buf, buflen, "CIPHER - The selected feature is not available" );
+ if( use_ret == -(POLARSSL_ERR_CIPHER_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "CIPHER - Bad input parameters to function" );
+ if( use_ret == -(POLARSSL_ERR_CIPHER_ALLOC_FAILED) )
+ snprintf( buf, buflen, "CIPHER - Failed to allocate memory" );
+ if( use_ret == -(POLARSSL_ERR_CIPHER_INVALID_PADDING) )
+ snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" );
+ if( use_ret == -(POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED) )
+ snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" );
+#endif /* POLARSSL_CIPHER_C */
+
+#if defined(POLARSSL_DHM_C)
+ if( use_ret == -(POLARSSL_ERR_DHM_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "DHM - Bad input parameters to function" );
+ if( use_ret == -(POLARSSL_ERR_DHM_READ_PARAMS_FAILED) )
+ snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" );
+ if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED) )
+ snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" );
+ if( use_ret == -(POLARSSL_ERR_DHM_READ_PUBLIC_FAILED) )
+ snprintf( buf, buflen, "DHM - Reading of the public values failed" );
+ if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED) )
+ snprintf( buf, buflen, "DHM - Making of the public value failed" );
+ if( use_ret == -(POLARSSL_ERR_DHM_CALC_SECRET_FAILED) )
+ snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" );
+#endif /* POLARSSL_DHM_C */
+
+#if defined(POLARSSL_MD_C)
+ if( use_ret == -(POLARSSL_ERR_MD_FEATURE_UNAVAILABLE) )
+ snprintf( buf, buflen, "MD - The selected feature is not available" );
+ if( use_ret == -(POLARSSL_ERR_MD_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "MD - Bad input parameters to function" );
+ if( use_ret == -(POLARSSL_ERR_MD_ALLOC_FAILED) )
+ snprintf( buf, buflen, "MD - Failed to allocate memory" );
+ if( use_ret == -(POLARSSL_ERR_MD_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "MD - Opening or reading of file failed" );
+#endif /* POLARSSL_MD_C */
+
+#if defined(POLARSSL_PEM_C)
+ if( use_ret == -(POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT) )
+ snprintf( buf, buflen, "PEM - No PEM header or footer found" );
+ if( use_ret == -(POLARSSL_ERR_PEM_INVALID_DATA) )
+ snprintf( buf, buflen, "PEM - PEM string is not as expected" );
+ if( use_ret == -(POLARSSL_ERR_PEM_MALLOC_FAILED) )
+ snprintf( buf, buflen, "PEM - Failed to allocate memory" );
+ if( use_ret == -(POLARSSL_ERR_PEM_INVALID_ENC_IV) )
+ snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" );
+ if( use_ret == -(POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG) )
+ snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" );
+ if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_REQUIRED) )
+ snprintf( buf, buflen, "PEM - Private key password can't be empty" );
+ if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_MISMATCH) )
+ snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" );
+ if( use_ret == -(POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE) )
+ snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" );
+ if( use_ret == -(POLARSSL_ERR_PEM_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "PEM - Bad input parameters to function" );
+#endif /* POLARSSL_PEM_C */
+
+#if defined(POLARSSL_PKCS12_C)
+ if( use_ret == -(POLARSSL_ERR_PKCS12_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "PKCS12 - Bad input parameters to function" );
+ if( use_ret == -(POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE) )
+ snprintf( buf, buflen, "PKCS12 - Feature not available, e.g. unsupported encryption scheme" );
+ if( use_ret == -(POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT) )
+ snprintf( buf, buflen, "PKCS12 - PBE ASN.1 data not as expected" );
+ if( use_ret == -(POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH) )
+ snprintf( buf, buflen, "PKCS12 - Given private key password does not allow for correct decryption" );
+#endif /* POLARSSL_PKCS12_C */
+
+#if defined(POLARSSL_PKCS5_C)
+ if( use_ret == -(POLARSSL_ERR_PKCS5_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "PKCS5 - Bad input parameters to function" );
+ if( use_ret == -(POLARSSL_ERR_PKCS5_INVALID_FORMAT) )
+ snprintf( buf, buflen, "PKCS5 - Unexpected ASN.1 data" );
+ if( use_ret == -(POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE) )
+ snprintf( buf, buflen, "PKCS5 - Requested encryption or digest alg not available" );
+ if( use_ret == -(POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH) )
+ snprintf( buf, buflen, "PKCS5 - Given private key password does not allow for correct decryption" );
+#endif /* POLARSSL_PKCS5_C */
+
+#if defined(POLARSSL_RSA_C)
+ if( use_ret == -(POLARSSL_ERR_RSA_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "RSA - Bad input parameters to function" );
+ if( use_ret == -(POLARSSL_ERR_RSA_INVALID_PADDING) )
+ snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" );
+ if( use_ret == -(POLARSSL_ERR_RSA_KEY_GEN_FAILED) )
+ snprintf( buf, buflen, "RSA - Something failed during generation of a key" );
+ if( use_ret == -(POLARSSL_ERR_RSA_KEY_CHECK_FAILED) )
+ snprintf( buf, buflen, "RSA - Key failed to pass the libraries validity check" );
+ if( use_ret == -(POLARSSL_ERR_RSA_PUBLIC_FAILED) )
+ snprintf( buf, buflen, "RSA - The public key operation failed" );
+ if( use_ret == -(POLARSSL_ERR_RSA_PRIVATE_FAILED) )
+ snprintf( buf, buflen, "RSA - The private key operation failed" );
+ if( use_ret == -(POLARSSL_ERR_RSA_VERIFY_FAILED) )
+ snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" );
+ if( use_ret == -(POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE) )
+ snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" );
+ if( use_ret == -(POLARSSL_ERR_RSA_RNG_FAILED) )
+ snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" );
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_SSL_TLS_C)
+ if( use_ret == -(POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE) )
+ snprintf( buf, buflen, "SSL - The requested feature is not available" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "SSL - Bad input parameters to function" );
+ if( use_ret == -(POLARSSL_ERR_SSL_INVALID_MAC) )
+ snprintf( buf, buflen, "SSL - Verification of the message MAC failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_INVALID_RECORD) )
+ snprintf( buf, buflen, "SSL - An invalid SSL record was received" );
+ if( use_ret == -(POLARSSL_ERR_SSL_CONN_EOF) )
+ snprintf( buf, buflen, "SSL - The connection indicated an EOF" );
+ if( use_ret == -(POLARSSL_ERR_SSL_UNKNOWN_CIPHER) )
+ snprintf( buf, buflen, "SSL - An unknown cipher was received" );
+ if( use_ret == -(POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN) )
+ snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" );
+ if( use_ret == -(POLARSSL_ERR_SSL_NO_SESSION_FOUND) )
+ snprintf( buf, buflen, "SSL - No session to recover was found" );
+ if( use_ret == -(POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE) )
+ snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" );
+ if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE) )
+ snprintf( buf, buflen, "SSL - DESCRIPTION MISSING" );
+ if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED) )
+ snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" );
+ if( use_ret == -(POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED) )
+ snprintf( buf, buflen, "SSL - The own private key is not set, but needed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED) )
+ snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" );
+ if( use_ret == -(POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE) )
+ snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" );
+ if( use_ret == -(POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE) )
+ {
+ snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" );
+ return;
+ }
+ if( use_ret == -(POLARSSL_ERR_SSL_PEER_VERIFY_FAILED) )
+ snprintf( buf, buflen, "SSL - Verification of our peer failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) )
+ snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO) )
+ snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO) )
+ snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE) )
+ snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) )
+ snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) )
+ snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) )
+ snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) )
+ snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP) )
+ snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM Read Public" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS) )
+ snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM Calculate Secret" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) )
+ snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) )
+ snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_FINISHED) )
+ snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_MALLOC_FAILED) )
+ snprintf( buf, buflen, "SSL - Memory allocation failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_HW_ACCEL_FAILED) )
+ snprintf( buf, buflen, "SSL - Hardware acceleration function returned with error" );
+ if( use_ret == -(POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH) )
+ snprintf( buf, buflen, "SSL - Hardware acceleration function skipped / left alone data" );
+ if( use_ret == -(POLARSSL_ERR_SSL_COMPRESSION_FAILED) )
+ snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION) )
+ snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" );
+#endif /* POLARSSL_SSL_TLS_C */
+
+#if defined(POLARSSL_X509_PARSE_C)
+ if( use_ret == -(POLARSSL_ERR_X509_FEATURE_UNAVAILABLE) )
+ snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_PEM) )
+ snprintf( buf, buflen, "X509 - The PEM-encoded certificate contains invalid elements, e.g. invalid character" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_FORMAT) )
+ snprintf( buf, buflen, "X509 - The certificate format is invalid, e.g. different type expected" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_VERSION) )
+ snprintf( buf, buflen, "X509 - The certificate version element is invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_SERIAL) )
+ snprintf( buf, buflen, "X509 - The serial tag or value is invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_ALG) )
+ snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_NAME) )
+ snprintf( buf, buflen, "X509 - The name tag or value is invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_DATE) )
+ snprintf( buf, buflen, "X509 - The date tag or value is invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_PUBKEY) )
+ snprintf( buf, buflen, "X509 - The pubkey tag or value is invalid (only RSA is supported)" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE) )
+ snprintf( buf, buflen, "X509 - The signature tag or value invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS) )
+ snprintf( buf, buflen, "X509 - The extension tag or value is invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION) )
+ snprintf( buf, buflen, "X509 - Certificate or CRL has an unsupported version number" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG) )
+ snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" );
+ if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_PK_ALG) )
+ snprintf( buf, buflen, "X509 - Key algorithm is unsupported (only RSA is supported)" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_SIG_MISMATCH) )
+ snprintf( buf, buflen, "X509 - Certificate signature algorithms do not match. (see \\c ::x509_cert sig_oid)" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_VERIFY_FAILED) )
+ snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" );
+ if( use_ret == -(POLARSSL_ERR_X509_KEY_INVALID_VERSION) )
+ snprintf( buf, buflen, "X509 - Unsupported RSA key version" );
+ if( use_ret == -(POLARSSL_ERR_X509_KEY_INVALID_FORMAT) )
+ snprintf( buf, buflen, "X509 - Invalid RSA key tag or value" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT) )
+ snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" );
+ if( use_ret == -(POLARSSL_ERR_X509_INVALID_INPUT) )
+ snprintf( buf, buflen, "X509 - Input invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_MALLOC_FAILED) )
+ snprintf( buf, buflen, "X509 - Allocation of memory failed" );
+ if( use_ret == -(POLARSSL_ERR_X509_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "X509 - Read/write of file failed" );
+ if( use_ret == -(POLARSSL_ERR_X509_PASSWORD_REQUIRED) )
+ snprintf( buf, buflen, "X509 - Private key password can't be empty" );
+ if( use_ret == -(POLARSSL_ERR_X509_PASSWORD_MISMATCH) )
+ snprintf( buf, buflen, "X509 - Given private key password does not allow for correct decryption" );
+#endif /* POLARSSL_X509_PARSE_C */
+
+ if( strlen( buf ) == 0 )
+ snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
+ }
+
+ use_ret = ret & ~0xFF80;
+
+ if( use_ret == 0 )
+ return;
+
+ // If high level code is present, make a concatenation between both
+ // error strings.
+ //
+ len = strlen( buf );
+
+ if( len > 0 )
+ {
+ if( buflen - len < 5 )
+ return;
+
+ snprintf( buf + len, buflen - len, " : " );
+
+ buf += len + 3;
+ buflen -= len + 3;
+ }
+
+ // Low level error codes
+ //
+#if defined(POLARSSL_AES_C)
+ if( use_ret == -(POLARSSL_ERR_AES_INVALID_KEY_LENGTH) )
+ snprintf( buf, buflen, "AES - Invalid key length" );
+ if( use_ret == -(POLARSSL_ERR_AES_INVALID_INPUT_LENGTH) )
+ snprintf( buf, buflen, "AES - Invalid data input length" );
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_ASN1_PARSE_C)
+ if( use_ret == -(POLARSSL_ERR_ASN1_OUT_OF_DATA) )
+ snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" );
+ if( use_ret == -(POLARSSL_ERR_ASN1_UNEXPECTED_TAG) )
+ snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" );
+ if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_LENGTH) )
+ snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" );
+ if( use_ret == -(POLARSSL_ERR_ASN1_LENGTH_MISMATCH) )
+ snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" );
+ if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_DATA) )
+ snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" );
+ if( use_ret == -(POLARSSL_ERR_ASN1_MALLOC_FAILED) )
+ snprintf( buf, buflen, "ASN1 - Memory allocation failed" );
+ if( use_ret == -(POLARSSL_ERR_ASN1_BUF_TOO_SMALL) )
+ snprintf( buf, buflen, "ASN1 - Buffer too small when writing ASN.1 data structure" );
+#endif /* POLARSSL_ASN1_PARSE_C */
+
+#if defined(POLARSSL_BASE64_C)
+ if( use_ret == -(POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL) )
+ snprintf( buf, buflen, "BASE64 - Output buffer too small" );
+ if( use_ret == -(POLARSSL_ERR_BASE64_INVALID_CHARACTER) )
+ snprintf( buf, buflen, "BASE64 - Invalid character in input" );
+#endif /* POLARSSL_BASE64_C */
+
+#if defined(POLARSSL_BIGNUM_C)
+ if( use_ret == -(POLARSSL_ERR_MPI_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" );
+ if( use_ret == -(POLARSSL_ERR_MPI_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" );
+ if( use_ret == -(POLARSSL_ERR_MPI_INVALID_CHARACTER) )
+ snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" );
+ if( use_ret == -(POLARSSL_ERR_MPI_BUFFER_TOO_SMALL) )
+ snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" );
+ if( use_ret == -(POLARSSL_ERR_MPI_NEGATIVE_VALUE) )
+ snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" );
+ if( use_ret == -(POLARSSL_ERR_MPI_DIVISION_BY_ZERO) )
+ snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" );
+ if( use_ret == -(POLARSSL_ERR_MPI_NOT_ACCEPTABLE) )
+ snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" );
+ if( use_ret == -(POLARSSL_ERR_MPI_MALLOC_FAILED) )
+ snprintf( buf, buflen, "BIGNUM - Memory allocation failed" );
+#endif /* POLARSSL_BIGNUM_C */
+
+#if defined(POLARSSL_BLOWFISH_C)
+ if( use_ret == -(POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH) )
+ snprintf( buf, buflen, "BLOWFISH - Invalid key length" );
+ if( use_ret == -(POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH) )
+ snprintf( buf, buflen, "BLOWFISH - Invalid data input length" );
+#endif /* POLARSSL_BLOWFISH_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+ if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH) )
+ snprintf( buf, buflen, "CAMELLIA - Invalid key length" );
+ if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH) )
+ snprintf( buf, buflen, "CAMELLIA - Invalid data input length" );
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_CTR_DRBG_C)
+ if( use_ret == -(POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) )
+ snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" );
+ if( use_ret == -(POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG) )
+ snprintf( buf, buflen, "CTR_DRBG - Too many random requested in single call" );
+ if( use_ret == -(POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG) )
+ snprintf( buf, buflen, "CTR_DRBG - Input too large (Entropy + additional)" );
+ if( use_ret == -(POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "CTR_DRBG - Read/write error in file" );
+#endif /* POLARSSL_CTR_DRBG_C */
+
+#if defined(POLARSSL_DES_C)
+ if( use_ret == -(POLARSSL_ERR_DES_INVALID_INPUT_LENGTH) )
+ snprintf( buf, buflen, "DES - The data input has an invalid length" );
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ENTROPY_C)
+ if( use_ret == -(POLARSSL_ERR_ENTROPY_SOURCE_FAILED) )
+ snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" );
+ if( use_ret == -(POLARSSL_ERR_ENTROPY_MAX_SOURCES) )
+ snprintf( buf, buflen, "ENTROPY - No more sources can be added" );
+ if( use_ret == -(POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED) )
+ snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" );
+#endif /* POLARSSL_ENTROPY_C */
+
+#if defined(POLARSSL_GCM_C)
+ if( use_ret == -(POLARSSL_ERR_GCM_AUTH_FAILED) )
+ snprintf( buf, buflen, "GCM - Authenticated decryption failed" );
+ if( use_ret == -(POLARSSL_ERR_GCM_BAD_INPUT) )
+ snprintf( buf, buflen, "GCM - Bad input parameters to function" );
+#endif /* POLARSSL_GCM_C */
+
+#if defined(POLARSSL_MD2_C)
+ if( use_ret == -(POLARSSL_ERR_MD2_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "MD2 - Read/write error in file" );
+#endif /* POLARSSL_MD2_C */
+
+#if defined(POLARSSL_MD4_C)
+ if( use_ret == -(POLARSSL_ERR_MD4_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "MD4 - Read/write error in file" );
+#endif /* POLARSSL_MD4_C */
+
+#if defined(POLARSSL_MD5_C)
+ if( use_ret == -(POLARSSL_ERR_MD5_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "MD5 - Read/write error in file" );
+#endif /* POLARSSL_MD5_C */
+
+#if defined(POLARSSL_NET_C)
+ if( use_ret == -(POLARSSL_ERR_NET_UNKNOWN_HOST) )
+ snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" );
+ if( use_ret == -(POLARSSL_ERR_NET_SOCKET_FAILED) )
+ snprintf( buf, buflen, "NET - Failed to open a socket" );
+ if( use_ret == -(POLARSSL_ERR_NET_CONNECT_FAILED) )
+ snprintf( buf, buflen, "NET - The connection to the given server / port failed" );
+ if( use_ret == -(POLARSSL_ERR_NET_BIND_FAILED) )
+ snprintf( buf, buflen, "NET - Binding of the socket failed" );
+ if( use_ret == -(POLARSSL_ERR_NET_LISTEN_FAILED) )
+ snprintf( buf, buflen, "NET - Could not listen on the socket" );
+ if( use_ret == -(POLARSSL_ERR_NET_ACCEPT_FAILED) )
+ snprintf( buf, buflen, "NET - Could not accept the incoming connection" );
+ if( use_ret == -(POLARSSL_ERR_NET_RECV_FAILED) )
+ snprintf( buf, buflen, "NET - Reading information from the socket failed" );
+ if( use_ret == -(POLARSSL_ERR_NET_SEND_FAILED) )
+ snprintf( buf, buflen, "NET - Sending information through the socket failed" );
+ if( use_ret == -(POLARSSL_ERR_NET_CONN_RESET) )
+ snprintf( buf, buflen, "NET - Connection was reset by peer" );
+ if( use_ret == -(POLARSSL_ERR_NET_WANT_READ) )
+ snprintf( buf, buflen, "NET - Connection requires a read call" );
+ if( use_ret == -(POLARSSL_ERR_NET_WANT_WRITE) )
+ snprintf( buf, buflen, "NET - Connection requires a write call" );
+#endif /* POLARSSL_NET_C */
+
+#if defined(POLARSSL_PADLOCK_C)
+ if( use_ret == -(POLARSSL_ERR_PADLOCK_DATA_MISALIGNED) )
+ snprintf( buf, buflen, "PADLOCK - Input data should be aligned" );
+#endif /* POLARSSL_PADLOCK_C */
+
+#if defined(POLARSSL_PBKDF2_C)
+ if( use_ret == -(POLARSSL_ERR_PBKDF2_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "PBKDF2 - Bad input parameters to function" );
+#endif /* POLARSSL_PBKDF2_C */
+
+#if defined(POLARSSL_SHA1_C)
+ if( use_ret == -(POLARSSL_ERR_SHA1_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "SHA1 - Read/write error in file" );
+#endif /* POLARSSL_SHA1_C */
+
+#if defined(POLARSSL_SHA2_C)
+ if( use_ret == -(POLARSSL_ERR_SHA2_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "SHA2 - Read/write error in file" );
+#endif /* POLARSSL_SHA2_C */
+
+#if defined(POLARSSL_SHA4_C)
+ if( use_ret == -(POLARSSL_ERR_SHA4_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "SHA4 - Read/write error in file" );
+#endif /* POLARSSL_SHA4_C */
+
+#if defined(POLARSSL_XTEA_C)
+ if( use_ret == -(POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH) )
+ snprintf( buf, buflen, "XTEA - The data input has an invalid length" );
+#endif /* POLARSSL_XTEA_C */
+
+ if( strlen( buf ) != 0 )
+ return;
+
+ snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
+}
+
+#else /* POLARSSL_ERROR_C */
+
+#if defined(POLARSSL_ERROR_STRERROR_DUMMY)
+
+#include
+
+/*
+ * Provide an non-function in case POLARSSL_ERROR_C is not defined
+ */
+void error_strerror( int ret, char *buf, size_t buflen )
+{
+ ((void) ret);
+
+ if( buflen > 0 )
+ buf[0] = '\0';
+}
+
+#endif /* POLARSSL_ERROR_STRERROR_DUMMY */
+#endif /* POLARSSL_ERROR_C */
diff --git a/polarssl/error.h b/polarssl/error.h
new file mode 100644
index 0000000..94c73a8
--- /dev/null
+++ b/polarssl/error.h
@@ -0,0 +1,108 @@
+/**
+ * \file error.h
+ *
+ * \brief Error to string translation
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ERROR_H
+#define POLARSSL_ERROR_H
+
+#include
+
+/**
+ * Error code layout.
+ *
+ * Currently we try to keep all error codes within the negative space of 16
+ * bytes signed integers to support all platforms (-0x0000 - -0x8000). In
+ * addition we'd like to give two layers of information on the error if
+ * possible.
+ *
+ * For that purpose the error codes are segmented in the following manner:
+ *
+ * 16 bit error code bit-segmentation
+ *
+ * 1 bit - Intentionally not used
+ * 3 bits - High level module ID
+ * 5 bits - Module-dependent error code
+ * 6 bits - Low level module errors
+ * 1 bit - Intentionally not used
+ *
+ * Low-level module errors (0x007E-0x0002)
+ *
+ * Module Nr Codes assigned
+ * MPI 7 0x0002-0x0010
+ * GCM 2 0x0012-0x0014
+ * BLOWFISH 2 0x0016-0x0018
+ * AES 2 0x0020-0x0022
+ * CAMELLIA 2 0x0024-0x0026
+ * XTEA 1 0x0028-0x0028
+ * BASE64 2 0x002A-0x002C
+ * PADLOCK 1 0x0030-0x0030
+ * DES 1 0x0032-0x0032
+ * CTR_DBRG 3 0x0034-0x003A
+ * ENTROPY 3 0x003C-0x0040
+ * NET 11 0x0042-0x0056
+ * ASN1 7 0x0060-0x006C
+ * MD2 1 0x0070-0x0070
+ * MD4 1 0x0072-0x0072
+ * MD5 1 0x0074-0x0074
+ * SHA1 1 0x0076-0x0076
+ * SHA2 1 0x0078-0x0078
+ * SHA4 1 0x007A-0x007A
+ *
+ * High-level module nr (3 bits - 0x1...-0x8...)
+ * Name ID Nr of Errors
+ * PEM 1 9
+ * PKCS#12 1 4 (Started from top)
+ * X509 2 23
+ * DHM 3 6
+ * PKCS5 3 4 (Started from top)
+ * RSA 4 9
+ * MD 5 4
+ * CIPHER 6 5
+ * SSL 6 2 (Started from top)
+ * SSL 7 31
+ *
+ * Module dependent error code (5 bits 0x.08.-0x.F8.)
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Translate a PolarSSL error code into a string representation,
+ * Result is truncated if necessary and always includes a terminating
+ * null byte.
+ *
+ * \param errnum error code
+ * \param buffer buffer to place representation in
+ * \param buflen length of the buffer
+ */
+void error_strerror( int errnum, char *buffer, size_t buflen );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* error.h */
diff --git a/polarssl/gcm.c b/polarssl/gcm.c
new file mode 100644
index 0000000..60dc0cd
--- /dev/null
+++ b/polarssl/gcm.c
@@ -0,0 +1,621 @@
+/*
+ * NIST SP800-38D compliant GCM implementation
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
+ */
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_GCM_C)
+
+#include "polarssl/gcm.h"
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+static void gcm_gen_table( gcm_context *ctx )
+{
+ int i, j;
+ uint64_t hi, lo;
+ uint64_t vl, vh;
+ unsigned char h[16];
+
+ memset( h, 0, 16 );
+ aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, h, h );
+
+ ctx->HH[0] = 0;
+ ctx->HL[0] = 0;
+
+ GET_UINT32_BE( hi, h, 0 );
+ GET_UINT32_BE( lo, h, 4 );
+ vh = (uint64_t) hi << 32 | lo;
+
+ GET_UINT32_BE( hi, h, 8 );
+ GET_UINT32_BE( lo, h, 12 );
+ vl = (uint64_t) hi << 32 | lo;
+
+ ctx->HL[8] = vl;
+ ctx->HH[8] = vh;
+
+ for( i = 4; i > 0; i >>= 1 )
+ {
+ uint32_t T = ( vl & 1 ) * 0xe1000000U;
+ vl = ( vh << 63 ) | ( vl >> 1 );
+ vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
+
+ ctx->HL[i] = vl;
+ ctx->HH[i] = vh;
+ }
+
+ for (i = 2; i < 16; i <<= 1 )
+ {
+ uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
+ vh = *HiH;
+ vl = *HiL;
+ for( j = 1; j < i; j++ )
+ {
+ HiH[j] = vh ^ ctx->HH[j];
+ HiL[j] = vl ^ ctx->HL[j];
+ }
+ }
+
+}
+
+int gcm_init( gcm_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+ int ret;
+
+ memset( ctx, 0, sizeof(gcm_context) );
+
+ if( ( ret = aes_setkey_enc( &ctx->aes_ctx, key, keysize ) ) != 0 )
+ return( ret );
+
+ gcm_gen_table( ctx );
+
+ return( 0 );
+}
+
+static const uint64_t last4[16] =
+{
+ 0x0000, 0x1c20, 0x3840, 0x2460,
+ 0x7080, 0x6ca0, 0x48c0, 0x54e0,
+ 0xe100, 0xfd20, 0xd940, 0xc560,
+ 0x9180, 0x8da0, 0xa9c0, 0xb5e0
+};
+
+void gcm_mult( gcm_context *ctx, const unsigned char x[16], unsigned char output[16] )
+{
+ int i = 0;
+ unsigned char z[16];
+ unsigned char lo, hi, rem;
+ uint64_t zh, zl;
+
+ memset( z, 0x00, 16 );
+
+ lo = x[15] & 0xf;
+ hi = x[15] >> 4;
+
+ zh = ctx->HH[lo];
+ zl = ctx->HL[lo];
+
+ for( i = 15; i >= 0; i-- )
+ {
+ lo = x[i] & 0xf;
+ hi = x[i] >> 4;
+
+ if( i != 15 )
+ {
+ rem = (unsigned char) zl & 0xf;
+ zl = ( zh << 60 ) | ( zl >> 4 );
+ zh = ( zh >> 4 );
+ zh ^= (uint64_t) last4[rem] << 48;
+ zh ^= ctx->HH[lo];
+ zl ^= ctx->HL[lo];
+
+ }
+
+ rem = (unsigned char) zl & 0xf;
+ zl = ( zh << 60 ) | ( zl >> 4 );
+ zh = ( zh >> 4 );
+ zh ^= (uint64_t) last4[rem] << 48;
+ zh ^= ctx->HH[hi];
+ zl ^= ctx->HL[hi];
+ }
+
+ PUT_UINT32_BE( zh >> 32, output, 0 );
+ PUT_UINT32_BE( zh, output, 4 );
+ PUT_UINT32_BE( zl >> 32, output, 8 );
+ PUT_UINT32_BE( zl, output, 12 );
+}
+
+int gcm_crypt_and_tag( gcm_context *ctx,
+ int mode,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t tag_len,
+ unsigned char *tag )
+{
+ unsigned char y[16];
+ unsigned char ectr[16];
+ unsigned char buf[16];
+ unsigned char work_buf[16];
+ size_t i;
+ const unsigned char *p;
+ unsigned char *out_p = output;
+ size_t use_len;
+ uint64_t orig_len = length * 8;
+ uint64_t orig_add_len = add_len * 8;
+
+ memset( y, 0x00, 16 );
+ memset( work_buf, 0x00, 16 );
+ memset( tag, 0x00, tag_len );
+ memset( buf, 0x00, 16 );
+
+ if( ( mode == GCM_DECRYPT && output <= input && ( input - output ) < 8 ) ||
+ ( output > input && (size_t) ( output - input ) < length ) )
+ {
+ return( POLARSSL_ERR_GCM_BAD_INPUT );
+ }
+
+ if( iv_len == 12 )
+ {
+ memcpy( y, iv, iv_len );
+ y[15] = 1;
+ }
+ else
+ {
+ memset( work_buf, 0x00, 16 );
+ PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
+
+ p = iv;
+ while( iv_len > 0 )
+ {
+ use_len = ( iv_len < 16 ) ? iv_len : 16;
+
+ for( i = 0; i < use_len; i++ )
+ y[i] ^= p[i];
+
+ gcm_mult( ctx, y, y );
+
+ iv_len -= use_len;
+ p += use_len;
+ }
+
+ for( i = 0; i < 16; i++ )
+ y[i] ^= work_buf[i];
+
+ gcm_mult( ctx, y, y );
+ }
+
+ aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, y, ectr );
+ memcpy( tag, ectr, tag_len );
+
+ p = add;
+ while( add_len > 0 )
+ {
+ use_len = ( add_len < 16 ) ? add_len : 16;
+
+ for( i = 0; i < use_len; i++ )
+ buf[i] ^= p[i];
+
+ gcm_mult( ctx, buf, buf );
+
+ add_len -= use_len;
+ p += use_len;
+ }
+
+ p = input;
+ while( length > 0 )
+ {
+ use_len = ( length < 16 ) ? length : 16;
+
+ for( i = 16; i > 12; i-- )
+ if( ++y[i - 1] != 0 )
+ break;
+
+ aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, y, ectr );
+
+ for( i = 0; i < use_len; i++ )
+ {
+ out_p[i] = ectr[i] ^ p[i];
+ if( mode == GCM_ENCRYPT )
+ buf[i] ^= out_p[i];
+ else
+ buf[i] ^= p[i];
+ }
+
+ gcm_mult( ctx, buf, buf );
+
+ length -= use_len;
+ p += use_len;
+ out_p += use_len;
+ }
+
+ if( orig_len || orig_add_len )
+ {
+ memset( work_buf, 0x00, 16 );
+
+ PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
+ PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
+ PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
+ PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
+
+ for( i = 0; i < 16; i++ )
+ buf[i] ^= work_buf[i];
+
+ gcm_mult( ctx, buf, buf );
+
+ for( i = 0; i < tag_len; i++ )
+ tag[i] ^= buf[i];
+ }
+
+ return( 0 );
+}
+
+int gcm_auth_decrypt( gcm_context *ctx,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *tag,
+ size_t tag_len,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ unsigned char check_tag[16];
+
+ gcm_crypt_and_tag( ctx, GCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag_len, check_tag );
+
+ if( memcmp( check_tag, tag, tag_len ) == 0 )
+ return( 0 );
+
+ memset( output, 0, length );
+
+ return( POLARSSL_ERR_GCM_AUTH_FAILED );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include
+
+/*
+ * GCM test vectors from:
+ *
+ * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
+ */
+#define MAX_TESTS 6
+
+int key_index[MAX_TESTS] =
+ { 0, 0, 1, 1, 1, 1 };
+
+unsigned char key[MAX_TESTS][32] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+};
+
+size_t iv_len[MAX_TESTS] =
+ { 12, 12, 12, 12, 8, 60 };
+
+int iv_index[MAX_TESTS] =
+ { 0, 0, 1, 1, 1, 2 };
+
+unsigned char iv[MAX_TESTS][64] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 },
+ { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
+ 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
+ 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
+ 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
+ 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
+ 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
+ 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
+ 0xa6, 0x37, 0xb3, 0x9b },
+};
+
+size_t add_len[MAX_TESTS] =
+ { 0, 0, 0, 20, 20, 20 };
+
+int add_index[MAX_TESTS] =
+ { 0, 0, 0, 1, 1, 1 };
+
+unsigned char additional[MAX_TESTS][64] =
+{
+ { 0x00 },
+ { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2 },
+};
+
+size_t pt_len[MAX_TESTS] =
+ { 0, 16, 64, 60, 60, 60 };
+
+int pt_index[MAX_TESTS] =
+ { 0, 0, 1, 1, 1, 1 };
+
+unsigned char pt[MAX_TESTS][64] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
+};
+
+unsigned char ct[MAX_TESTS * 3][64] =
+{
+ { 0x00 },
+ { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
+ 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
+ { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
+ { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91 },
+ { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
+ 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
+ 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
+ 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
+ 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
+ 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
+ 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
+ 0xc2, 0x3f, 0x45, 0x98 },
+ { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
+ 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
+ 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
+ 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
+ 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
+ 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
+ 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
+ 0x4c, 0x34, 0xae, 0xe5 },
+ { 0x00 },
+ { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
+ 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
+ { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+ 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+ 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+ 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+ 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+ 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+ 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+ 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
+ { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+ 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+ 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+ 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+ 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+ 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+ 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+ 0xcc, 0xda, 0x27, 0x10 },
+ { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
+ 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
+ 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
+ 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
+ 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
+ 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
+ 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
+ 0xa0, 0xf0, 0x62, 0xf7 },
+ { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
+ 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
+ 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
+ 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
+ 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
+ 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
+ 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
+ 0xe9, 0xb7, 0x37, 0x3b },
+ { 0x00 },
+ { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
+ 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
+ { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+ 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+ 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+ 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+ 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+ 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+ 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+ 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
+ { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+ 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+ 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+ 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+ 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+ 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+ 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+ 0xbc, 0xc9, 0xf6, 0x62 },
+ { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
+ 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
+ 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
+ 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
+ 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
+ 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
+ 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
+ 0xf4, 0x7c, 0x9b, 0x1f },
+ { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
+ 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
+ 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
+ 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
+ 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
+ 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
+ 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
+ 0x44, 0xae, 0x7e, 0x3f },
+};
+
+unsigned char tag[MAX_TESTS * 3][16] =
+{
+ { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
+ 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
+ { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
+ 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
+ { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+ 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
+ { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
+ 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
+ { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
+ 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
+ { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
+ 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
+ { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
+ 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
+ { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
+ 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
+ { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
+ 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
+ { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
+ 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
+ { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
+ 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
+ { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
+ 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
+ { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
+ 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
+ { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
+ 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
+ { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
+ 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
+ { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
+ 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
+ { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
+ 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
+ { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
+ 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
+};
+
+int gcm_self_test( int verbose )
+{
+ gcm_context ctx;
+ unsigned char buf[64];
+ unsigned char tag_buf[16];
+ int i, j, ret;
+
+ for( j = 0; j < 3; j++ )
+ {
+ int key_len = 128 + 64 * j;
+
+ for( i = 0; i < MAX_TESTS; i++ )
+ {
+ printf( " AES-GCM-%3d #%d (%s): ", key_len, i, "enc" );
+ gcm_init( &ctx, key[key_index[i]], key_len );
+
+ ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT,
+ pt_len[i],
+ iv[iv_index[i]], iv_len[i],
+ additional[add_index[i]], add_len[i],
+ pt[pt_index[i]], buf, 16, tag_buf );
+
+ if( ret != 0 ||
+ memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
+ memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ printf( " AES-GCM-%3d #%d (%s): ", key_len, i, "dec" );
+ gcm_init( &ctx, key[key_index[i]], key_len );
+
+ ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT,
+ pt_len[i],
+ iv[iv_index[i]], iv_len[i],
+ additional[add_index[i]], add_len[i],
+ ct[j * 6 + i], buf, 16, tag_buf );
+
+ if( ret != 0 ||
+ memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
+ memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+ }
+
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/gcm.h b/polarssl/gcm.h
new file mode 100644
index 0000000..b3df62c
--- /dev/null
+++ b/polarssl/gcm.h
@@ -0,0 +1,147 @@
+/**
+ * \file gcm.h
+ *
+ * \brief Galois/Counter mode for AES
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_GCM_H
+#define POLARSSL_GCM_H
+
+#include "polarssl/aes.h"
+
+#ifdef _MSC_VER
+#include
+typedef UINT64 uint64_t;
+#else
+#include
+#endif
+
+#define GCM_ENCRYPT 1
+#define GCM_DECRYPT 0
+
+#define POLARSSL_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */
+#define POLARSSL_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */
+
+/**
+ * \brief GCM context structure
+ */
+typedef struct {
+ aes_context aes_ctx; /*!< AES context used */
+ uint64_t HL[16]; /*!< Precalculated HTable */
+ uint64_t HH[16]; /*!< Precalculated HTable */
+}
+gcm_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief GCM initialization (encryption)
+ *
+ * \param ctx GCM context to be initialized
+ * \param key encryption key
+ * \param keysize must be 128, 192 or 256
+ *
+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ */
+int gcm_init( gcm_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief GCM buffer encryption/decryption using AES
+ *
+ * \note On encryption, the output buffer can be the same as the input buffer.
+ * On decryption, the output buffer cannot be the same as input buffer.
+ * If buffers overlap, the output buffer must trail at least 8 bytes
+ * behind the input buffer.
+ *
+ * \param ctx GCM context
+ * \param mode GCM_ENCRYPT or GCM_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector
+ * \param iv_len length of IV
+ * \param add additional data
+ * \param add_len length of additional data
+ * \param input buffer holding the input data
+ * \param output buffer for holding the output data
+ * \param tag_len length of the tag to generate
+ * \param tag buffer for holding the tag
+ *
+ * \return 0 if successful
+ */
+int gcm_crypt_and_tag( gcm_context *ctx,
+ int mode,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t tag_len,
+ unsigned char *tag );
+
+/**
+ * \brief GCM buffer authenticated decryption using AES
+ *
+ * \note On decryption, the output buffer cannot be the same as input buffer.
+ * If buffers overlap, the output buffer must trail at least 8 bytes
+ * behind the input buffer.
+ *
+ * \param ctx GCM context
+ * \param length length of the input data
+ * \param iv initialization vector
+ * \param iv_len length of IV
+ * \param add additional data
+ * \param add_len length of additional data
+ * \param tag buffer holding the tag
+ * \param tag_len length of the tag
+ * \param input buffer holding the input data
+ * \param output buffer for holding the output data
+ *
+ * \return 0 if successful and authenticated,
+ * POLARSSL_ERR_GCM_AUTH_FAILED if tag does not match
+ */
+int gcm_auth_decrypt( gcm_context *ctx,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *tag,
+ size_t tag_len,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int gcm_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* gcm.h */
diff --git a/polarssl/havege.c b/polarssl/havege.c
new file mode 100644
index 0000000..ff302c5
--- /dev/null
+++ b/polarssl/havege.c
@@ -0,0 +1,231 @@
+/**
+ * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The HAVEGE RNG was designed by Andre Seznec in 2002.
+ *
+ * http://www.irisa.fr/caps/projects/hipsor/publi.php
+ *
+ * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_HAVEGE_C)
+
+#include "polarssl/havege.h"
+#include "polarssl/timing.h"
+
+#include
+#include
+
+/* ------------------------------------------------------------------------
+ * On average, one iteration accesses two 8-word blocks in the havege WALK
+ * table, and generates 16 words in the RES array.
+ *
+ * The data read in the WALK table is updated and permuted after each use.
+ * The result of the hardware clock counter read is used for this update.
+ *
+ * 25 conditional tests are present. The conditional tests are grouped in
+ * two nested groups of 12 conditional tests and 1 test that controls the
+ * permutation; on average, there should be 6 tests executed and 3 of them
+ * should be mispredicted.
+ * ------------------------------------------------------------------------
+ */
+
+#define SWAP(X,Y) { int *T = X; X = Y; Y = T; }
+
+#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
+#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
+
+#define TST1_LEAVE U1++; }
+#define TST2_LEAVE U2++; }
+
+#define ONE_ITERATION \
+ \
+ PTEST = PT1 >> 20; \
+ \
+ TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
+ TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
+ TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
+ \
+ TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
+ TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
+ TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
+ \
+ PTX = (PT1 >> 18) & 7; \
+ PT1 &= 0x1FFF; \
+ PT2 &= 0x1FFF; \
+ CLK = (int) hardclock(); \
+ \
+ i = 0; \
+ A = &WALK[PT1 ]; RES[i++] ^= *A; \
+ B = &WALK[PT2 ]; RES[i++] ^= *B; \
+ C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \
+ D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \
+ \
+ IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \
+ *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \
+ *B = IN ^ U1; \
+ *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \
+ *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \
+ \
+ A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \
+ B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \
+ C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \
+ D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \
+ \
+ if( PTEST & 1 ) SWAP( A, C ); \
+ \
+ IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \
+ *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \
+ *B = IN; CLK = (int) hardclock(); \
+ *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \
+ *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \
+ \
+ A = &WALK[PT1 ^ 4]; \
+ B = &WALK[PT2 ^ 1]; \
+ \
+ PTEST = PT2 >> 1; \
+ \
+ PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \
+ PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \
+ PTY = (PT2 >> 10) & 7; \
+ \
+ TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
+ TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
+ TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
+ \
+ TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
+ TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
+ TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
+ \
+ C = &WALK[PT1 ^ 5]; \
+ D = &WALK[PT2 ^ 5]; \
+ \
+ RES[i++] ^= *A; \
+ RES[i++] ^= *B; \
+ RES[i++] ^= *C; \
+ RES[i++] ^= *D; \
+ \
+ IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \
+ *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \
+ *B = IN ^ U2; \
+ *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \
+ *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \
+ \
+ A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \
+ B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \
+ C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \
+ D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \
+ \
+ IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \
+ *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \
+ *B = IN; \
+ *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \
+ *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \
+ \
+ PT1 = ( RES[(i - 8) ^ PTX] ^ \
+ WALK[PT1 ^ PTX ^ 7] ) & (~1); \
+ PT1 ^= (PT2 ^ 0x10) & 0x10; \
+ \
+ for( n++, i = 0; i < 16; i++ ) \
+ hs->pool[n % COLLECT_SIZE] ^= RES[i];
+
+/*
+ * Entropy gathering function
+ */
+static void havege_fill( havege_state *hs )
+{
+ int i, n = 0;
+ int U1, U2, *A, *B, *C, *D;
+ int PT1, PT2, *WALK, RES[16];
+ int PTX, PTY, CLK, PTEST, IN;
+
+ WALK = hs->WALK;
+ PT1 = hs->PT1;
+ PT2 = hs->PT2;
+
+ PTX = U1 = 0;
+ PTY = U2 = 0;
+
+ memset( RES, 0, sizeof( RES ) );
+
+ while( n < COLLECT_SIZE * 4 )
+ {
+ ONE_ITERATION
+ ONE_ITERATION
+ ONE_ITERATION
+ ONE_ITERATION
+ }
+
+ hs->PT1 = PT1;
+ hs->PT2 = PT2;
+
+ hs->offset[0] = 0;
+ hs->offset[1] = COLLECT_SIZE / 2;
+}
+
+/*
+ * HAVEGE initialization
+ */
+void havege_init( havege_state *hs )
+{
+ memset( hs, 0, sizeof( havege_state ) );
+
+ havege_fill( hs );
+}
+
+/*
+ * HAVEGE rand function
+ */
+int havege_random( void *p_rng, unsigned char *buf, size_t len )
+{
+ int val;
+ size_t use_len;
+ havege_state *hs = (havege_state *) p_rng;
+ unsigned char *p = buf;
+
+ while( len > 0 )
+ {
+ use_len = len;
+ if( use_len > sizeof(int) )
+ use_len = sizeof(int);
+
+ if( hs->offset[1] >= COLLECT_SIZE )
+ havege_fill( hs );
+
+ val = hs->pool[hs->offset[0]++];
+ val ^= hs->pool[hs->offset[1]++];
+
+ memcpy( p, &val, use_len );
+
+ len -= use_len;
+ p += use_len;
+ }
+
+ return( 0 );
+}
+
+#endif
diff --git a/polarssl/havege.h b/polarssl/havege.h
new file mode 100644
index 0000000..53c4f38
--- /dev/null
+++ b/polarssl/havege.h
@@ -0,0 +1,71 @@
+/**
+ * \file havege.h
+ *
+ * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_HAVEGE_H
+#define POLARSSL_HAVEGE_H
+
+#include
+
+#define COLLECT_SIZE 1024
+
+/**
+ * \brief HAVEGE state structure
+ */
+typedef struct
+{
+ int PT1, PT2, offset[2];
+ int pool[COLLECT_SIZE];
+ int WALK[8192];
+}
+havege_state;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief HAVEGE initialization
+ *
+ * \param hs HAVEGE state to be initialized
+ */
+void havege_init( havege_state *hs );
+
+/**
+ * \brief HAVEGE rand function
+ *
+ * \param p_rng A HAVEGE state
+ * \param output Buffer to fill
+ * \param len Length of buffer
+ *
+ * \return 0
+ */
+int havege_random( void *p_rng, unsigned char *output, size_t len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* havege.h */
diff --git a/polarssl/md.c b/polarssl/md.c
new file mode 100644
index 0000000..ab0f468
--- /dev/null
+++ b/polarssl/md.c
@@ -0,0 +1,298 @@
+/**
+ * \file md.c
+ *
+ * \brief Generic message digest wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_MD_C)
+
+#include "polarssl/md.h"
+#include "polarssl/md_wrap.h"
+
+#include
+#include
+
+//#if defined _MSC_VER && !defined strcasecmp
+//#define strcasecmp _stricmp
+//#endif
+
+static const int supported_digests[] = {
+
+#if defined(POLARSSL_MD2_C)
+ POLARSSL_MD_MD2,
+#endif
+
+#if defined(POLARSSL_MD4_C)
+ POLARSSL_MD_MD4,
+#endif
+
+#if defined(POLARSSL_MD5_C)
+ POLARSSL_MD_MD5,
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+ POLARSSL_MD_SHA1,
+#endif
+
+#if defined(POLARSSL_SHA2_C)
+ POLARSSL_MD_SHA224,
+ POLARSSL_MD_SHA256,
+#endif
+
+#if defined(POLARSSL_SHA4_C)
+ POLARSSL_MD_SHA384,
+ POLARSSL_MD_SHA512,
+#endif
+
+ 0
+};
+
+const int *md_list( void )
+{
+ return supported_digests;
+}
+
+const md_info_t *md_info_from_string( const char *md_name )
+{
+ if( NULL == md_name )
+ return NULL;
+
+ /* Get the appropriate digest information */
+#if defined(POLARSSL_MD2_C)
+ if( !strcasecmp( "MD2", md_name ) )
+ return md_info_from_type( POLARSSL_MD_MD2 );
+#endif
+#if defined(POLARSSL_MD4_C)
+ if( !strcasecmp( "MD4", md_name ) )
+ return md_info_from_type( POLARSSL_MD_MD4 );
+#endif
+#if defined(POLARSSL_MD5_C)
+ if( !strcasecmp( "MD5", md_name ) )
+ return md_info_from_type( POLARSSL_MD_MD5 );
+#endif
+#if defined(POLARSSL_SHA1_C)
+ if( !strcasecmp( "SHA1", md_name ) || !strcasecmp( "SHA", md_name ) )
+ return md_info_from_type( POLARSSL_MD_SHA1 );
+#endif
+#if defined(POLARSSL_SHA2_C)
+ if( !strcasecmp( "SHA224", md_name ) )
+ return md_info_from_type( POLARSSL_MD_SHA224 );
+ if( !strcasecmp( "SHA256", md_name ) )
+ return md_info_from_type( POLARSSL_MD_SHA256 );
+#endif
+#if defined(POLARSSL_SHA4_C)
+ if( !strcasecmp( "SHA384", md_name ) )
+ return md_info_from_type( POLARSSL_MD_SHA384 );
+ if( !strcasecmp( "SHA512", md_name ) )
+ return md_info_from_type( POLARSSL_MD_SHA512 );
+#endif
+ return NULL;
+}
+
+const md_info_t *md_info_from_type( md_type_t md_type )
+{
+ switch( md_type )
+ {
+#if defined(POLARSSL_MD2_C)
+ case POLARSSL_MD_MD2:
+ return &md2_info;
+#endif
+#if defined(POLARSSL_MD4_C)
+ case POLARSSL_MD_MD4:
+ return &md4_info;
+#endif
+#if defined(POLARSSL_MD5_C)
+ case POLARSSL_MD_MD5:
+ return &md5_info;
+#endif
+#if defined(POLARSSL_SHA1_C)
+ case POLARSSL_MD_SHA1:
+ return &sha1_info;
+#endif
+#if defined(POLARSSL_SHA2_C)
+ case POLARSSL_MD_SHA224:
+ return &sha224_info;
+ case POLARSSL_MD_SHA256:
+ return &sha256_info;
+#endif
+#if defined(POLARSSL_SHA4_C)
+ case POLARSSL_MD_SHA384:
+ return &sha384_info;
+ case POLARSSL_MD_SHA512:
+ return &sha512_info;
+#endif
+ default:
+ return NULL;
+ }
+}
+
+int md_init_ctx( md_context_t *ctx, const md_info_t *md_info )
+{
+ if( md_info == NULL || ctx == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ memset( ctx, 0, sizeof( md_context_t ) );
+
+ if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL )
+ return POLARSSL_ERR_MD_ALLOC_FAILED;
+
+ ctx->md_info = md_info;
+
+ md_info->starts_func( ctx->md_ctx );
+
+ return 0;
+}
+
+int md_free_ctx( md_context_t *ctx )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->ctx_free_func( ctx->md_ctx );
+ ctx->md_ctx = NULL;
+
+ return 0;
+}
+
+int md_starts( md_context_t *ctx )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->starts_func( ctx->md_ctx );
+
+ return 0;
+}
+
+int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->update_func( ctx->md_ctx, input, ilen );
+
+ return 0;
+}
+
+int md_finish( md_context_t *ctx, unsigned char *output )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->finish_func( ctx->md_ctx, output );
+
+ return 0;
+}
+
+int md( const md_info_t *md_info, const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ if ( md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ md_info->digest_func( input, ilen, output );
+
+ return 0;
+}
+
+int md_file( const md_info_t *md_info, const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ int ret;
+#endif
+
+ if( md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+#if defined(POLARSSL_FS_IO)
+ ret = md_info->file_func( path, output );
+ if( ret != 0 )
+ return( POLARSSL_ERR_MD_FILE_IO_ERROR + ret );
+
+ return( ret );
+#else
+ ((void) path);
+ ((void) output);
+
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->hmac_starts_func( ctx->md_ctx, key, keylen);
+
+ return 0;
+}
+
+int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->hmac_update_func( ctx->md_ctx, input, ilen );
+
+ return 0;
+}
+
+int md_hmac_finish( md_context_t *ctx, unsigned char *output)
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->hmac_finish_func( ctx->md_ctx, output);
+
+ return 0;
+}
+
+int md_hmac_reset( md_context_t *ctx )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->hmac_reset_func( ctx->md_ctx);
+
+ return 0;
+}
+
+int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ if( md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ md_info->hmac_func( key, keylen, input, ilen, output );
+
+ return 0;
+}
+
+#endif
diff --git a/polarssl/md.h b/polarssl/md.h
new file mode 100644
index 0000000..6a1bdd4
--- /dev/null
+++ b/polarssl/md.h
@@ -0,0 +1,363 @@
+/**
+ * \file md.h
+ *
+ * \brief Generic message digest wrapper
+ *
+ * \author Adriaan de Jong
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD_H
+#define POLARSSL_MD_H
+
+#include
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */
+#define POLARSSL_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */
+#define POLARSSL_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */
+
+typedef enum {
+ POLARSSL_MD_NONE=0,
+ POLARSSL_MD_MD2,
+ POLARSSL_MD_MD4,
+ POLARSSL_MD_MD5,
+ POLARSSL_MD_SHA1,
+ POLARSSL_MD_SHA224,
+ POLARSSL_MD_SHA256,
+ POLARSSL_MD_SHA384,
+ POLARSSL_MD_SHA512,
+} md_type_t;
+
+#define POLARSSL_MD_MAX_SIZE 64 /* longest known is SHA512 */
+
+/**
+ * Message digest information. Allows message digest functions to be called
+ * in a generic way.
+ */
+typedef struct {
+ /** Digest identifier */
+ md_type_t type;
+
+ /** Name of the message digest */
+ const char * name;
+
+ /** Output length of the digest function */
+ int size;
+
+ /** Digest initialisation function */
+ void (*starts_func)( void *ctx );
+
+ /** Digest update function */
+ void (*update_func)( void *ctx, const unsigned char *input, size_t ilen );
+
+ /** Digest finalisation function */
+ void (*finish_func)( void *ctx, unsigned char *output );
+
+ /** Generic digest function */
+ void (*digest_func)( const unsigned char *input, size_t ilen,
+ unsigned char *output );
+
+ /** Generic file digest function */
+ int (*file_func)( const char *path, unsigned char *output );
+
+ /** HMAC Initialisation function */
+ void (*hmac_starts_func)( void *ctx, const unsigned char *key, size_t keylen );
+
+ /** HMAC update function */
+ void (*hmac_update_func)( void *ctx, const unsigned char *input, size_t ilen );
+
+ /** HMAC finalisation function */
+ void (*hmac_finish_func)( void *ctx, unsigned char *output);
+
+ /** HMAC context reset function */
+ void (*hmac_reset_func)( void *ctx );
+
+ /** Generic HMAC function */
+ void (*hmac_func)( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output );
+
+ /** Allocate a new context */
+ void * (*ctx_alloc_func)( void );
+
+ /** Free the given context */
+ void (*ctx_free_func)( void *ctx );
+
+} md_info_t;
+
+/**
+ * Generic message digest context.
+ */
+typedef struct {
+ /** Information about the associated message digest */
+ const md_info_t *md_info;
+
+ /** Digest-specific context */
+ void *md_ctx;
+} md_context_t;
+
+#define MD_CONTEXT_T_INIT { \
+ NULL, /* md_info */ \
+ NULL, /* md_ctx */ \
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Returns the list of digests supported by the generic digest module.
+ *
+ * \return a statically allocated array of digests, the last entry
+ * is 0.
+ */
+const int *md_list( void );
+
+/**
+ * \brief Returns the message digest information associated with the
+ * given digest name.
+ *
+ * \param md_name Name of the digest to search for.
+ *
+ * \return The message digest information associated with md_name or
+ * NULL if not found.
+ */
+const md_info_t *md_info_from_string( const char *md_name );
+
+/**
+ * \brief Returns the message digest information associated with the
+ * given digest type.
+ *
+ * \param md_type type of digest to search for.
+ *
+ * \return The message digest information associated with md_type or
+ * NULL if not found.
+ */
+const md_info_t *md_info_from_type( md_type_t md_type );
+
+/**
+ * \brief Initialises and fills the message digest context structure with
+ * the appropriate values.
+ *
+ * \param ctx context to initialise. May not be NULL. The
+ * digest-specific context (ctx->md_ctx) must be NULL. It will
+ * be allocated, and must be freed using md_free_ctx() later.
+ * \param md_info message digest to use.
+ *
+ * \returns \c 0 on success, \c POLARSSL_ERR_MD_BAD_INPUT_DATA on
+ * parameter failure, \c POLARSSL_ERR_MD_ALLOC_FAILED if
+ * allocation of the digest-specific context failed.
+ */
+int md_init_ctx( md_context_t *ctx, const md_info_t *md_info );
+
+/**
+ * \brief Free the message-specific context of ctx. Freeing ctx itself
+ * remains the responsibility of the caller.
+ *
+ * \param ctx Free the message-specific context
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_free_ctx( md_context_t *ctx );
+
+/**
+ * \brief Returns the size of the message digest output.
+ *
+ * \param md_info message digest info
+ *
+ * \return size of the message digest output.
+ */
+static inline unsigned char md_get_size( const md_info_t *md_info )
+{
+ if( md_info == NULL )
+ return( 0 );
+
+ return md_info->size;
+}
+
+/**
+ * \brief Returns the type of the message digest output.
+ *
+ * \param md_info message digest info
+ *
+ * \return type of the message digest output.
+ */
+static inline md_type_t md_get_type( const md_info_t *md_info )
+{
+ if( md_info == NULL )
+ return( POLARSSL_MD_NONE );
+
+ return md_info->type;
+}
+
+/**
+ * \brief Returns the name of the message digest output.
+ *
+ * \param md_info message digest info
+ *
+ * \return name of the message digest output.
+ */
+static inline const char *md_get_name( const md_info_t *md_info )
+{
+ if( md_info == NULL )
+ return( NULL );
+
+ return md_info->name;
+}
+
+/**
+ * \brief Set-up the given context for a new message digest
+ *
+ * \param ctx generic message digest context.
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_starts( md_context_t *ctx );
+
+/**
+ * \brief Generic message digest process buffer
+ *
+ * \param ctx Generic message digest context
+ * \param input buffer holding the datal
+ * \param ilen length of the input data
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief Generic message digest final digest
+ *
+ * \param ctx Generic message digest context
+ * \param output Generic message digest checksum result
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_finish( md_context_t *ctx, unsigned char *output );
+
+/**
+ * \brief Output = message_digest( input buffer )
+ *
+ * \param md_info message digest info
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output Generic message digest checksum result
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md( const md_info_t *md_info, const unsigned char *input, size_t ilen,
+ unsigned char *output );
+
+/**
+ * \brief Output = message_digest( file contents )
+ *
+ * \param md_info message digest info
+ * \param path input file name
+ * \param output generic message digest checksum result
+ *
+ * \return 0 if successful, POLARSSL_ERR_MD_FILE_OPEN_FAILED if fopen
+ * failed, POLARSSL_ERR_MD_FILE_READ_FAILED if fread failed,
+ * POLARSSL_ERR_MD_BAD_INPUT_DATA if md_info was NULL.
+ */
+int md_file( const md_info_t *md_info, const char *path, unsigned char *output );
+
+/**
+ * \brief Generic HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen );
+
+/**
+ * \brief Generic HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief Generic HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output Generic HMAC checksum result
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_hmac_finish( md_context_t *ctx, unsigned char *output);
+
+/**
+ * \brief Generic HMAC context reset
+ *
+ * \param ctx HMAC context to be reset
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_hmac_reset( md_context_t *ctx );
+
+/**
+ * \brief Output = Generic_HMAC( hmac key, input buffer )
+ *
+ * \param md_info message digest info
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output Generic HMAC-result
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_MD_H */
diff --git a/polarssl/md2.c b/polarssl/md2.c
new file mode 100644
index 0000000..2c8754a
--- /dev/null
+++ b/polarssl/md2.c
@@ -0,0 +1,368 @@
+/*
+ * RFC 1115/1319 compliant MD2 implementation
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The MD2 algorithm was designed by Ron Rivest in 1989.
+ *
+ * http://www.ietf.org/rfc/rfc1115.txt
+ * http://www.ietf.org/rfc/rfc1319.txt
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_MD2_C)
+
+#include "polarssl/md2.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include
+#endif
+
+#if !defined(POLARSSL_MD2_ALT)
+
+static const unsigned char PI_SUBST[256] =
+{
+ 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36,
+ 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3,
+ 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C,
+ 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
+ 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E,
+ 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E,
+ 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2,
+ 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
+ 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E,
+ 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3,
+ 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56,
+ 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
+ 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D,
+ 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65,
+ 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0,
+ 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
+ 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C,
+ 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E,
+ 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81,
+ 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
+ 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88,
+ 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE,
+ 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58,
+ 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
+ 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99,
+ 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
+};
+
+/*
+ * MD2 context setup
+ */
+void md2_starts( md2_context *ctx )
+{
+ memset( ctx->cksum, 0, 16 );
+ memset( ctx->state, 0, 46 );
+ memset( ctx->buffer, 0, 16 );
+ ctx->left = 0;
+}
+
+static void md2_process( md2_context *ctx )
+{
+ int i, j;
+ unsigned char t = 0;
+
+ for( i = 0; i < 16; i++ )
+ {
+ ctx->state[i + 16] = ctx->buffer[i];
+ ctx->state[i + 32] =
+ (unsigned char)( ctx->buffer[i] ^ ctx->state[i]);
+ }
+
+ for( i = 0; i < 18; i++ )
+ {
+ for( j = 0; j < 48; j++ )
+ {
+ ctx->state[j] = (unsigned char)
+ ( ctx->state[j] ^ PI_SUBST[t] );
+ t = ctx->state[j];
+ }
+
+ t = (unsigned char)( t + i );
+ }
+
+ t = ctx->cksum[15];
+
+ for( i = 0; i < 16; i++ )
+ {
+ ctx->cksum[i] = (unsigned char)
+ ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] );
+ t = ctx->cksum[i];
+ }
+}
+
+/*
+ * MD2 process buffer
+ */
+void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen )
+{
+ size_t fill;
+
+ while( ilen > 0 )
+ {
+ if( ctx->left + ilen > 16 )
+ fill = 16 - ctx->left;
+ else
+ fill = ilen;
+
+ memcpy( ctx->buffer + ctx->left, input, fill );
+
+ ctx->left += fill;
+ input += fill;
+ ilen -= fill;
+
+ if( ctx->left == 16 )
+ {
+ ctx->left = 0;
+ md2_process( ctx );
+ }
+ }
+}
+
+/*
+ * MD2 final digest
+ */
+void md2_finish( md2_context *ctx, unsigned char output[16] )
+{
+ size_t i;
+ unsigned char x;
+
+ x = (unsigned char)( 16 - ctx->left );
+
+ for( i = ctx->left; i < 16; i++ )
+ ctx->buffer[i] = x;
+
+ md2_process( ctx );
+
+ memcpy( ctx->buffer, ctx->cksum, 16 );
+ md2_process( ctx );
+
+ memcpy( output, ctx->state, 16 );
+}
+
+#endif /* !POLARSSL_MD2_ALT */
+
+/*
+ * output = MD2( input buffer )
+ */
+void md2( const unsigned char *input, size_t ilen, unsigned char output[16] )
+{
+ md2_context ctx;
+
+ md2_starts( &ctx );
+ md2_update( &ctx, input, ilen );
+ md2_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md2_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = MD2( file contents )
+ */
+int md2_file( const char *path, unsigned char output[16] )
+{
+ FILE *f;
+ size_t n;
+ md2_context ctx;
+ unsigned char buf[1024];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_MD2_FILE_IO_ERROR );
+
+ md2_starts( &ctx );
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ md2_update( &ctx, buf, n );
+
+ md2_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md2_context ) );
+
+ if( ferror( f ) != 0 )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_MD2_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * MD2 HMAC context setup
+ */
+void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen )
+{
+ size_t i;
+ unsigned char sum[16];
+
+ if( keylen > 16 )
+ {
+ md2( key, keylen, sum );
+ keylen = 16;
+ key = sum;
+ }
+
+ memset( ctx->ipad, 0x36, 16 );
+ memset( ctx->opad, 0x5C, 16 );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+ ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+ }
+
+ md2_starts( ctx );
+ md2_update( ctx, ctx->ipad, 16 );
+
+ memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * MD2 HMAC process buffer
+ */
+void md2_hmac_update( md2_context *ctx, const unsigned char *input, size_t ilen )
+{
+ md2_update( ctx, input, ilen );
+}
+
+/*
+ * MD2 HMAC final digest
+ */
+void md2_hmac_finish( md2_context *ctx, unsigned char output[16] )
+{
+ unsigned char tmpbuf[16];
+
+ md2_finish( ctx, tmpbuf );
+ md2_starts( ctx );
+ md2_update( ctx, ctx->opad, 16 );
+ md2_update( ctx, tmpbuf, 16 );
+ md2_finish( ctx, output );
+
+ memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * MD2 HMAC context reset
+ */
+void md2_hmac_reset( md2_context *ctx )
+{
+ md2_starts( ctx );
+ md2_update( ctx, ctx->ipad, 16 );
+}
+
+/*
+ * output = HMAC-MD2( hmac key, input buffer )
+ */
+void md2_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[16] )
+{
+ md2_context ctx;
+
+ md2_hmac_starts( &ctx, key, keylen );
+ md2_hmac_update( &ctx, input, ilen );
+ md2_hmac_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md2_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * RFC 1319 test vectors
+ */
+static const char md2_test_str[7][81] =
+{
+ { "" },
+ { "a" },
+ { "abc" },
+ { "message digest" },
+ { "abcdefghijklmnopqrstuvwxyz" },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+ { "12345678901234567890123456789012345678901234567890123456789012" \
+ "345678901234567890" }
+};
+
+static const unsigned char md2_test_sum[7][16] =
+{
+ { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D,
+ 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 },
+ { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72,
+ 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 },
+ { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B,
+ 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB },
+ { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B,
+ 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 },
+ { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB,
+ 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B },
+ { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39,
+ 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD },
+ { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D,
+ 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 }
+};
+
+/*
+ * Checkup routine
+ */
+int md2_self_test( int verbose )
+{
+ int i;
+ unsigned char md2sum[16];
+
+ for( i = 0; i < 7; i++ )
+ {
+ if( verbose != 0 )
+ printf( " MD2 test #%d: ", i + 1 );
+
+ md2( (unsigned char *) md2_test_str[i],
+ strlen( md2_test_str[i] ), md2sum );
+
+ if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/md2.h b/polarssl/md2.h
new file mode 100644
index 0000000..f437242
--- /dev/null
+++ b/polarssl/md2.h
@@ -0,0 +1,171 @@
+/**
+ * \file md2.h
+ *
+ * \brief MD2 message digest algorithm (hash function)
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD2_H
+#define POLARSSL_MD2_H
+
+#include "polarssl/config.h"
+
+#include
+
+#define POLARSSL_ERR_MD2_FILE_IO_ERROR -0x0070 /**< Read/write error in file. */
+
+#if !defined(POLARSSL_MD2_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief MD2 context structure
+ */
+typedef struct
+{
+ unsigned char cksum[16]; /*!< checksum of the data block */
+ unsigned char state[48]; /*!< intermediate digest state */
+ unsigned char buffer[16]; /*!< data block being processed */
+
+ unsigned char ipad[16]; /*!< HMAC: inner padding */
+ unsigned char opad[16]; /*!< HMAC: outer padding */
+ size_t left; /*!< amount of data in buffer */
+}
+md2_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief MD2 context setup
+ *
+ * \param ctx context to be initialized
+ */
+void md2_starts( md2_context *ctx );
+
+/**
+ * \brief MD2 process buffer
+ *
+ * \param ctx MD2 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief MD2 final digest
+ *
+ * \param ctx MD2 context
+ * \param output MD2 checksum result
+ */
+void md2_finish( md2_context *ctx, unsigned char output[16] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* POLARSSL_MD2_ALT */
+#include "polarssl/md2_alt.h"
+#endif /* POLARSSL_MD2_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Output = MD2( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output MD2 checksum result
+ */
+void md2( const unsigned char *input, size_t ilen, unsigned char output[16] );
+
+/**
+ * \brief Output = MD2( file contents )
+ *
+ * \param path input file name
+ * \param output MD2 checksum result
+ *
+ * \return 0 if successful, or POLARSSL_ERR_MD2_FILE_IO_ERROR
+ */
+int md2_file( const char *path, unsigned char output[16] );
+
+/**
+ * \brief MD2 HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ */
+void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen );
+
+/**
+ * \brief MD2 HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void md2_hmac_update( md2_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief MD2 HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output MD2 HMAC checksum result
+ */
+void md2_hmac_finish( md2_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief MD2 HMAC context reset
+ *
+ * \param ctx HMAC context to be reset
+ */
+void md2_hmac_reset( md2_context *ctx );
+
+/**
+ * \brief Output = HMAC-MD2( hmac key, input buffer )
+ *
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output HMAC-MD2 result
+ */
+void md2_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[16] );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int md2_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* md2.h */
diff --git a/polarssl/md4.c b/polarssl/md4.c
new file mode 100644
index 0000000..980f5e4
--- /dev/null
+++ b/polarssl/md4.c
@@ -0,0 +1,464 @@
+/*
+ * RFC 1186/1320 compliant MD4 implementation
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The MD4 algorithm was designed by Ron Rivest in 1990.
+ *
+ * http://www.ietf.org/rfc/rfc1186.txt
+ * http://www.ietf.org/rfc/rfc1320.txt
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_MD4_C)
+
+#include "polarssl/md4.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include
+#endif
+
+#if !defined(POLARSSL_MD4_ALT)
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] ) \
+ | ( (uint32_t) (b)[(i) + 1] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 3] << 24 ); \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
+}
+#endif
+
+/*
+ * MD4 context setup
+ */
+void md4_starts( md4_context *ctx )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+}
+
+static void md4_process( md4_context *ctx, const unsigned char data[64] )
+{
+ uint32_t X[16], A, B, C, D;
+
+ GET_UINT32_LE( X[ 0], data, 0 );
+ GET_UINT32_LE( X[ 1], data, 4 );
+ GET_UINT32_LE( X[ 2], data, 8 );
+ GET_UINT32_LE( X[ 3], data, 12 );
+ GET_UINT32_LE( X[ 4], data, 16 );
+ GET_UINT32_LE( X[ 5], data, 20 );
+ GET_UINT32_LE( X[ 6], data, 24 );
+ GET_UINT32_LE( X[ 7], data, 28 );
+ GET_UINT32_LE( X[ 8], data, 32 );
+ GET_UINT32_LE( X[ 9], data, 36 );
+ GET_UINT32_LE( X[10], data, 40 );
+ GET_UINT32_LE( X[11], data, 44 );
+ GET_UINT32_LE( X[12], data, 48 );
+ GET_UINT32_LE( X[13], data, 52 );
+ GET_UINT32_LE( X[14], data, 56 );
+ GET_UINT32_LE( X[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+
+#define F(x, y, z) ((x & y) | ((~x) & z))
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
+
+ P( A, B, C, D, X[ 0], 3 );
+ P( D, A, B, C, X[ 1], 7 );
+ P( C, D, A, B, X[ 2], 11 );
+ P( B, C, D, A, X[ 3], 19 );
+ P( A, B, C, D, X[ 4], 3 );
+ P( D, A, B, C, X[ 5], 7 );
+ P( C, D, A, B, X[ 6], 11 );
+ P( B, C, D, A, X[ 7], 19 );
+ P( A, B, C, D, X[ 8], 3 );
+ P( D, A, B, C, X[ 9], 7 );
+ P( C, D, A, B, X[10], 11 );
+ P( B, C, D, A, X[11], 19 );
+ P( A, B, C, D, X[12], 3 );
+ P( D, A, B, C, X[13], 7 );
+ P( C, D, A, B, X[14], 11 );
+ P( B, C, D, A, X[15], 19 );
+
+#undef P
+#undef F
+
+#define F(x,y,z) ((x & y) | (x & z) | (y & z))
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
+
+ P( A, B, C, D, X[ 0], 3 );
+ P( D, A, B, C, X[ 4], 5 );
+ P( C, D, A, B, X[ 8], 9 );
+ P( B, C, D, A, X[12], 13 );
+ P( A, B, C, D, X[ 1], 3 );
+ P( D, A, B, C, X[ 5], 5 );
+ P( C, D, A, B, X[ 9], 9 );
+ P( B, C, D, A, X[13], 13 );
+ P( A, B, C, D, X[ 2], 3 );
+ P( D, A, B, C, X[ 6], 5 );
+ P( C, D, A, B, X[10], 9 );
+ P( B, C, D, A, X[14], 13 );
+ P( A, B, C, D, X[ 3], 3 );
+ P( D, A, B, C, X[ 7], 5 );
+ P( C, D, A, B, X[11], 9 );
+ P( B, C, D, A, X[15], 13 );
+
+#undef P
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
+
+ P( A, B, C, D, X[ 0], 3 );
+ P( D, A, B, C, X[ 8], 9 );
+ P( C, D, A, B, X[ 4], 11 );
+ P( B, C, D, A, X[12], 15 );
+ P( A, B, C, D, X[ 2], 3 );
+ P( D, A, B, C, X[10], 9 );
+ P( C, D, A, B, X[ 6], 11 );
+ P( B, C, D, A, X[14], 15 );
+ P( A, B, C, D, X[ 1], 3 );
+ P( D, A, B, C, X[ 9], 9 );
+ P( C, D, A, B, X[ 5], 11 );
+ P( B, C, D, A, X[13], 15 );
+ P( A, B, C, D, X[ 3], 3 );
+ P( D, A, B, C, X[11], 9 );
+ P( C, D, A, B, X[ 7], 11 );
+ P( B, C, D, A, X[15], 15 );
+
+#undef F
+#undef P
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+}
+
+/*
+ * MD4 process buffer
+ */
+void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen )
+{
+ size_t fill;
+ uint32_t left;
+
+ if( ilen <= 0 )
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (uint32_t) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, fill );
+ md4_process( ctx, ctx->buffer );
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ md4_process( ctx, input );
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, ilen );
+ }
+}
+
+static const unsigned char md4_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * MD4 final digest
+ */
+void md4_finish( md4_context *ctx, unsigned char output[16] )
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT32_LE( low, msglen, 0 );
+ PUT_UINT32_LE( high, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ md4_update( ctx, (unsigned char *) md4_padding, padn );
+ md4_update( ctx, msglen, 8 );
+
+ PUT_UINT32_LE( ctx->state[0], output, 0 );
+ PUT_UINT32_LE( ctx->state[1], output, 4 );
+ PUT_UINT32_LE( ctx->state[2], output, 8 );
+ PUT_UINT32_LE( ctx->state[3], output, 12 );
+}
+
+#endif /* !POLARSSL_MD4_ALT */
+
+/*
+ * output = MD4( input buffer )
+ */
+void md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
+{
+ md4_context ctx;
+
+ md4_starts( &ctx );
+ md4_update( &ctx, input, ilen );
+ md4_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md4_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = MD4( file contents )
+ */
+int md4_file( const char *path, unsigned char output[16] )
+{
+ FILE *f;
+ size_t n;
+ md4_context ctx;
+ unsigned char buf[1024];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
+
+ md4_starts( &ctx );
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ md4_update( &ctx, buf, n );
+
+ md4_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md4_context ) );
+
+ if( ferror( f ) != 0 )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * MD4 HMAC context setup
+ */
+void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen )
+{
+ size_t i;
+ unsigned char sum[16];
+
+ if( keylen > 64 )
+ {
+ md4( key, keylen, sum );
+ keylen = 16;
+ key = sum;
+ }
+
+ memset( ctx->ipad, 0x36, 64 );
+ memset( ctx->opad, 0x5C, 64 );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+ ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+ }
+
+ md4_starts( ctx );
+ md4_update( ctx, ctx->ipad, 64 );
+
+ memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * MD4 HMAC process buffer
+ */
+void md4_hmac_update( md4_context *ctx, const unsigned char *input, size_t ilen )
+{
+ md4_update( ctx, input, ilen );
+}
+
+/*
+ * MD4 HMAC final digest
+ */
+void md4_hmac_finish( md4_context *ctx, unsigned char output[16] )
+{
+ unsigned char tmpbuf[16];
+
+ md4_finish( ctx, tmpbuf );
+ md4_starts( ctx );
+ md4_update( ctx, ctx->opad, 64 );
+ md4_update( ctx, tmpbuf, 16 );
+ md4_finish( ctx, output );
+
+ memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * MD4 HMAC context reset
+ */
+void md4_hmac_reset( md4_context *ctx )
+{
+ md4_starts( ctx );
+ md4_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-MD4( hmac key, input buffer )
+ */
+void md4_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[16] )
+{
+ md4_context ctx;
+
+ md4_hmac_starts( &ctx, key, keylen );
+ md4_hmac_update( &ctx, input, ilen );
+ md4_hmac_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md4_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * RFC 1320 test vectors
+ */
+static const char md4_test_str[7][81] =
+{
+ { "" },
+ { "a" },
+ { "abc" },
+ { "message digest" },
+ { "abcdefghijklmnopqrstuvwxyz" },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+ { "12345678901234567890123456789012345678901234567890123456789012" \
+ "345678901234567890" }
+};
+
+static const unsigned char md4_test_sum[7][16] =
+{
+ { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
+ 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
+ { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
+ 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
+ { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
+ 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
+ { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
+ 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
+ { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
+ 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
+ { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
+ 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
+ { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
+ 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
+};
+
+/*
+ * Checkup routine
+ */
+int md4_self_test( int verbose )
+{
+ int i;
+ unsigned char md4sum[16];
+
+ for( i = 0; i < 7; i++ )
+ {
+ if( verbose != 0 )
+ printf( " MD4 test #%d: ", i + 1 );
+
+ md4( (unsigned char *) md4_test_str[i],
+ strlen( md4_test_str[i] ), md4sum );
+
+ if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/md4.h b/polarssl/md4.h
new file mode 100644
index 0000000..9600361
--- /dev/null
+++ b/polarssl/md4.h
@@ -0,0 +1,177 @@
+/**
+ * \file md4.h
+ *
+ * \brief MD4 message digest algorithm (hash function)
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD4_H
+#define POLARSSL_MD4_H
+
+#include "polarssl/config.h"
+
+#include
+
+#ifdef _MSC_VER
+#include
+typedef UINT32 uint32_t;
+#else
+#include
+#endif
+
+#define POLARSSL_ERR_MD4_FILE_IO_ERROR -0x0072 /**< Read/write error in file. */
+
+#if !defined(POLARSSL_MD4_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief MD4 context structure
+ */
+typedef struct
+{
+ uint32_t total[2]; /*!< number of bytes processed */
+ uint32_t state[4]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+
+ unsigned char ipad[64]; /*!< HMAC: inner padding */
+ unsigned char opad[64]; /*!< HMAC: outer padding */
+}
+md4_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief MD4 context setup
+ *
+ * \param ctx context to be initialized
+ */
+void md4_starts( md4_context *ctx );
+
+/**
+ * \brief MD4 process buffer
+ *
+ * \param ctx MD4 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief MD4 final digest
+ *
+ * \param ctx MD4 context
+ * \param output MD4 checksum result
+ */
+void md4_finish( md4_context *ctx, unsigned char output[16] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* POLARSSL_MD4_ALT */
+#include "polarssl/md4_alt.h"
+#endif /* POLARSSL_MD4_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Output = MD4( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output MD4 checksum result
+ */
+void md4( const unsigned char *input, size_t ilen, unsigned char output[16] );
+
+/**
+ * \brief Output = MD4( file contents )
+ *
+ * \param path input file name
+ * \param output MD4 checksum result
+ *
+ * \return 0 if successful, or POLARSSL_ERR_MD4_FILE_IO_ERROR
+ */
+int md4_file( const char *path, unsigned char output[16] );
+
+/**
+ * \brief MD4 HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ */
+void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen );
+
+/**
+ * \brief MD4 HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void md4_hmac_update( md4_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief MD4 HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output MD4 HMAC checksum result
+ */
+void md4_hmac_finish( md4_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief MD4 HMAC context reset
+ *
+ * \param ctx HMAC context to be reset
+ */
+void md4_hmac_reset( md4_context *ctx );
+
+/**
+ * \brief Output = HMAC-MD4( hmac key, input buffer )
+ *
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output HMAC-MD4 result
+ */
+void md4_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[16] );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int md4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* md4.h */
diff --git a/polarssl/md5.c b/polarssl/md5.c
new file mode 100644
index 0000000..b28461e
--- /dev/null
+++ b/polarssl/md5.c
@@ -0,0 +1,585 @@
+/*
+ * RFC 1321 compliant MD5 implementation
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The MD5 algorithm was designed by Ron Rivest in 1991.
+ *
+ * http://www.ietf.org/rfc/rfc1321.txt
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_MD5_C)
+
+#include "polarssl/md5.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include
+#endif
+
+#if !defined(POLARSSL_MD5_ALT)
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] ) \
+ | ( (uint32_t) (b)[(i) + 1] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 3] << 24 ); \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
+}
+#endif
+
+/*
+ * MD5 context setup
+ */
+void md5_starts( md5_context *ctx )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+}
+
+void md5_process( md5_context *ctx, const unsigned char data[64] )
+{
+ uint32_t X[16], A, B, C, D;
+
+ GET_UINT32_LE( X[ 0], data, 0 );
+ GET_UINT32_LE( X[ 1], data, 4 );
+ GET_UINT32_LE( X[ 2], data, 8 );
+ GET_UINT32_LE( X[ 3], data, 12 );
+ GET_UINT32_LE( X[ 4], data, 16 );
+ GET_UINT32_LE( X[ 5], data, 20 );
+ GET_UINT32_LE( X[ 6], data, 24 );
+ GET_UINT32_LE( X[ 7], data, 28 );
+ GET_UINT32_LE( X[ 8], data, 32 );
+ GET_UINT32_LE( X[ 9], data, 36 );
+ GET_UINT32_LE( X[10], data, 40 );
+ GET_UINT32_LE( X[11], data, 44 );
+ GET_UINT32_LE( X[12], data, 48 );
+ GET_UINT32_LE( X[13], data, 52 );
+ GET_UINT32_LE( X[14], data, 56 );
+ GET_UINT32_LE( X[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define P(a,b,c,d,k,s,t) \
+{ \
+ a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+
+ P( A, B, C, D, 0, 7, 0xD76AA478 );
+ P( D, A, B, C, 1, 12, 0xE8C7B756 );
+ P( C, D, A, B, 2, 17, 0x242070DB );
+ P( B, C, D, A, 3, 22, 0xC1BDCEEE );
+ P( A, B, C, D, 4, 7, 0xF57C0FAF );
+ P( D, A, B, C, 5, 12, 0x4787C62A );
+ P( C, D, A, B, 6, 17, 0xA8304613 );
+ P( B, C, D, A, 7, 22, 0xFD469501 );
+ P( A, B, C, D, 8, 7, 0x698098D8 );
+ P( D, A, B, C, 9, 12, 0x8B44F7AF );
+ P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
+ P( B, C, D, A, 11, 22, 0x895CD7BE );
+ P( A, B, C, D, 12, 7, 0x6B901122 );
+ P( D, A, B, C, 13, 12, 0xFD987193 );
+ P( C, D, A, B, 14, 17, 0xA679438E );
+ P( B, C, D, A, 15, 22, 0x49B40821 );
+
+#undef F
+
+#define F(x,y,z) (y ^ (z & (x ^ y)))
+
+ P( A, B, C, D, 1, 5, 0xF61E2562 );
+ P( D, A, B, C, 6, 9, 0xC040B340 );
+ P( C, D, A, B, 11, 14, 0x265E5A51 );
+ P( B, C, D, A, 0, 20, 0xE9B6C7AA );
+ P( A, B, C, D, 5, 5, 0xD62F105D );
+ P( D, A, B, C, 10, 9, 0x02441453 );
+ P( C, D, A, B, 15, 14, 0xD8A1E681 );
+ P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
+ P( A, B, C, D, 9, 5, 0x21E1CDE6 );
+ P( D, A, B, C, 14, 9, 0xC33707D6 );
+ P( C, D, A, B, 3, 14, 0xF4D50D87 );
+ P( B, C, D, A, 8, 20, 0x455A14ED );
+ P( A, B, C, D, 13, 5, 0xA9E3E905 );
+ P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
+ P( C, D, A, B, 7, 14, 0x676F02D9 );
+ P( B, C, D, A, 12, 20, 0x8D2A4C8A );
+
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+
+ P( A, B, C, D, 5, 4, 0xFFFA3942 );
+ P( D, A, B, C, 8, 11, 0x8771F681 );
+ P( C, D, A, B, 11, 16, 0x6D9D6122 );
+ P( B, C, D, A, 14, 23, 0xFDE5380C );
+ P( A, B, C, D, 1, 4, 0xA4BEEA44 );
+ P( D, A, B, C, 4, 11, 0x4BDECFA9 );
+ P( C, D, A, B, 7, 16, 0xF6BB4B60 );
+ P( B, C, D, A, 10, 23, 0xBEBFBC70 );
+ P( A, B, C, D, 13, 4, 0x289B7EC6 );
+ P( D, A, B, C, 0, 11, 0xEAA127FA );
+ P( C, D, A, B, 3, 16, 0xD4EF3085 );
+ P( B, C, D, A, 6, 23, 0x04881D05 );
+ P( A, B, C, D, 9, 4, 0xD9D4D039 );
+ P( D, A, B, C, 12, 11, 0xE6DB99E5 );
+ P( C, D, A, B, 15, 16, 0x1FA27CF8 );
+ P( B, C, D, A, 2, 23, 0xC4AC5665 );
+
+#undef F
+
+#define F(x,y,z) (y ^ (x | ~z))
+
+ P( A, B, C, D, 0, 6, 0xF4292244 );
+ P( D, A, B, C, 7, 10, 0x432AFF97 );
+ P( C, D, A, B, 14, 15, 0xAB9423A7 );
+ P( B, C, D, A, 5, 21, 0xFC93A039 );
+ P( A, B, C, D, 12, 6, 0x655B59C3 );
+ P( D, A, B, C, 3, 10, 0x8F0CCC92 );
+ P( C, D, A, B, 10, 15, 0xFFEFF47D );
+ P( B, C, D, A, 1, 21, 0x85845DD1 );
+ P( A, B, C, D, 8, 6, 0x6FA87E4F );
+ P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
+ P( C, D, A, B, 6, 15, 0xA3014314 );
+ P( B, C, D, A, 13, 21, 0x4E0811A1 );
+ P( A, B, C, D, 4, 6, 0xF7537E82 );
+ P( D, A, B, C, 11, 10, 0xBD3AF235 );
+ P( C, D, A, B, 2, 15, 0x2AD7D2BB );
+ P( B, C, D, A, 9, 21, 0xEB86D391 );
+
+#undef F
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+}
+
+/*
+ * MD5 process buffer
+ */
+void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen )
+{
+ size_t fill;
+ uint32_t left;
+
+ if( ilen <= 0 )
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (uint32_t) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, fill );
+ md5_process( ctx, ctx->buffer );
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ md5_process( ctx, input );
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, ilen );
+ }
+}
+
+static const unsigned char md5_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * MD5 final digest
+ */
+void md5_finish( md5_context *ctx, unsigned char output[16] )
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT32_LE( low, msglen, 0 );
+ PUT_UINT32_LE( high, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ md5_update( ctx, md5_padding, padn );
+ md5_update( ctx, msglen, 8 );
+
+ PUT_UINT32_LE( ctx->state[0], output, 0 );
+ PUT_UINT32_LE( ctx->state[1], output, 4 );
+ PUT_UINT32_LE( ctx->state[2], output, 8 );
+ PUT_UINT32_LE( ctx->state[3], output, 12 );
+}
+
+#endif /* !POLARSSL_MD5_ALT */
+
+/*
+ * output = MD5( input buffer )
+ */
+void md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
+{
+ md5_context ctx;
+
+ md5_starts( &ctx );
+ md5_update( &ctx, input, ilen );
+ md5_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md5_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = MD5( file contents )
+ */
+int md5_file( const char *path, unsigned char output[16] )
+{
+ FILE *f;
+ size_t n;
+ md5_context ctx;
+ unsigned char buf[1024];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
+
+ md5_starts( &ctx );
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ md5_update( &ctx, buf, n );
+
+ md5_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md5_context ) );
+
+ if( ferror( f ) != 0 )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * MD5 HMAC context setup
+ */
+void md5_hmac_starts( md5_context *ctx, const unsigned char *key, size_t keylen )
+{
+ size_t i;
+ unsigned char sum[16];
+
+ if( keylen > 64 )
+ {
+ md5( key, keylen, sum );
+ keylen = 16;
+ key = sum;
+ }
+
+ memset( ctx->ipad, 0x36, 64 );
+ memset( ctx->opad, 0x5C, 64 );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+ ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+ }
+
+ md5_starts( ctx );
+ md5_update( ctx, ctx->ipad, 64 );
+
+ memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * MD5 HMAC process buffer
+ */
+void md5_hmac_update( md5_context *ctx, const unsigned char *input, size_t ilen )
+{
+ md5_update( ctx, input, ilen );
+}
+
+/*
+ * MD5 HMAC final digest
+ */
+void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
+{
+ unsigned char tmpbuf[16];
+
+ md5_finish( ctx, tmpbuf );
+ md5_starts( ctx );
+ md5_update( ctx, ctx->opad, 64 );
+ md5_update( ctx, tmpbuf, 16 );
+ md5_finish( ctx, output );
+
+ memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * MD5 HMAC context reset
+ */
+void md5_hmac_reset( md5_context *ctx )
+{
+ md5_starts( ctx );
+ md5_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-MD5( hmac key, input buffer )
+ */
+void md5_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[16] )
+{
+ md5_context ctx;
+
+ md5_hmac_starts( &ctx, key, keylen );
+ md5_hmac_update( &ctx, input, ilen );
+ md5_hmac_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md5_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * RFC 1321 test vectors
+ */
+static unsigned char md5_test_buf[7][81] =
+{
+ { "" },
+ { "a" },
+ { "abc" },
+ { "message digest" },
+ { "abcdefghijklmnopqrstuvwxyz" },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+ { "12345678901234567890123456789012345678901234567890123456789012" \
+ "345678901234567890" }
+};
+
+static const int md5_test_buflen[7] =
+{
+ 0, 1, 3, 14, 26, 62, 80
+};
+
+static const unsigned char md5_test_sum[7][16] =
+{
+ { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
+ 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
+ { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
+ 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
+ { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
+ 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
+ { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
+ 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
+ { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
+ 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
+ { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
+ 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
+ { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
+ 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
+};
+
+/*
+ * RFC 2202 test vectors
+ */
+static unsigned char md5_hmac_test_key[7][26] =
+{
+ { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" },
+ { "Jefe" },
+ { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" },
+ { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+ "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+ { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" },
+ { "" }, /* 0xAA 80 times */
+ { "" }
+};
+
+static const int md5_hmac_test_keylen[7] =
+{
+ 16, 4, 16, 25, 16, 80, 80
+};
+
+static unsigned char md5_hmac_test_buf[7][74] =
+{
+ { "Hi There" },
+ { "what do ya want for nothing?" },
+ { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+ { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+ { "Test With Truncation" },
+ { "Test Using Larger Than Block-Size Key - Hash Key First" },
+ { "Test Using Larger Than Block-Size Key and Larger"
+ " Than One Block-Size Data" }
+};
+
+static const int md5_hmac_test_buflen[7] =
+{
+ 8, 28, 50, 50, 20, 54, 73
+};
+
+static const unsigned char md5_hmac_test_sum[7][16] =
+{
+ { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C,
+ 0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D },
+ { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03,
+ 0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 },
+ { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88,
+ 0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 },
+ { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA,
+ 0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 },
+ { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00,
+ 0xF9, 0xBA, 0xB9, 0x95 },
+ { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F,
+ 0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD },
+ { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE,
+ 0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E }
+};
+
+/*
+ * Checkup routine
+ */
+int md5_self_test( int verbose )
+{
+ int i, buflen;
+ unsigned char buf[1024];
+ unsigned char md5sum[16];
+ md5_context ctx;
+
+ for( i = 0; i < 7; i++ )
+ {
+ if( verbose != 0 )
+ printf( " MD5 test #%d: ", i + 1 );
+
+ md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
+
+ if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ for( i = 0; i < 7; i++ )
+ {
+ if( verbose != 0 )
+ printf( " HMAC-MD5 test #%d: ", i + 1 );
+
+ if( i == 5 || i == 6 )
+ {
+ memset( buf, '\xAA', buflen = 80 );
+ md5_hmac_starts( &ctx, buf, buflen );
+ }
+ else
+ md5_hmac_starts( &ctx, md5_hmac_test_key[i],
+ md5_hmac_test_keylen[i] );
+
+ md5_hmac_update( &ctx, md5_hmac_test_buf[i],
+ md5_hmac_test_buflen[i] );
+
+ md5_hmac_finish( &ctx, md5sum );
+
+ buflen = ( i == 4 ) ? 12 : 16;
+
+ if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/md5.h b/polarssl/md5.h
new file mode 100644
index 0000000..ecb6428
--- /dev/null
+++ b/polarssl/md5.h
@@ -0,0 +1,182 @@
+/**
+ * \file md5.h
+ *
+ * \brief MD5 message digest algorithm (hash function)
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD5_H
+#define POLARSSL_MD5_H
+
+#include "polarssl/config.h"
+
+#include
+
+#ifdef _MSC_VER
+#include
+typedef UINT32 uint32_t;
+#else
+#include
+#endif
+
+#define POLARSSL_ERR_MD5_FILE_IO_ERROR -0x0074 /**< Read/write error in file. */
+
+#if !defined(POLARSSL_MD5_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief MD5 context structure
+ */
+typedef struct
+{
+ uint32_t total[2]; /*!< number of bytes processed */
+ uint32_t state[4]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+
+ unsigned char ipad[64]; /*!< HMAC: inner padding */
+ unsigned char opad[64]; /*!< HMAC: outer padding */
+}
+md5_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief MD5 context setup
+ *
+ * \param ctx context to be initialized
+ */
+void md5_starts( md5_context *ctx );
+
+/**
+ * \brief MD5 process buffer
+ *
+ * \param ctx MD5 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief MD5 final digest
+ *
+ * \param ctx MD5 context
+ * \param output MD5 checksum result
+ */
+void md5_finish( md5_context *ctx, unsigned char output[16] );
+
+/* Internal use */
+void md5_process( md5_context *ctx, const unsigned char data[64] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* POLARSSL_MD5_ALT */
+#include "polarssl/md5_alt.h"
+#endif /* POLARSSL_MD5_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Output = MD5( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output MD5 checksum result
+ */
+void md5( const unsigned char *input, size_t ilen, unsigned char output[16] );
+
+/**
+ * \brief Output = MD5( file contents )
+ *
+ * \param path input file name
+ * \param output MD5 checksum result
+ *
+ * \return 0 if successful, or POLARSSL_ERR_MD5_FILE_IO_ERROR
+ */
+int md5_file( const char *path, unsigned char output[16] );
+
+/**
+ * \brief MD5 HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ */
+void md5_hmac_starts( md5_context *ctx,
+ const unsigned char *key, size_t keylen );
+
+/**
+ * \brief MD5 HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void md5_hmac_update( md5_context *ctx,
+ const unsigned char *input, size_t ilen );
+
+/**
+ * \brief MD5 HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output MD5 HMAC checksum result
+ */
+void md5_hmac_finish( md5_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief MD5 HMAC context reset
+ *
+ * \param ctx HMAC context to be reset
+ */
+void md5_hmac_reset( md5_context *ctx );
+
+/**
+ * \brief Output = HMAC-MD5( hmac key, input buffer )
+ *
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output HMAC-MD5 result
+ */
+void md5_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[16] );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int md5_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* md5.h */
diff --git a/polarssl/md_wrap.c b/polarssl/md_wrap.c
new file mode 100644
index 0000000..f276db5
--- /dev/null
+++ b/polarssl/md_wrap.c
@@ -0,0 +1,733 @@
+/**
+ * \file md_wrap.c
+
+ * \brief Generic message digest wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_MD_C)
+
+#include "polarssl/md_wrap.h"
+
+#if defined(POLARSSL_MD2_C)
+#include "polarssl/md2.h"
+#endif
+
+#if defined(POLARSSL_MD4_C)
+#include "polarssl/md4.h"
+#endif
+
+#if defined(POLARSSL_MD5_C)
+#include "polarssl/md5.h"
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+#include "polarssl/sha1.h"
+#endif
+
+#if defined(POLARSSL_SHA2_C)
+#include "polarssl/sha2.h"
+#endif
+
+#if defined(POLARSSL_SHA4_C)
+#include "polarssl/sha4.h"
+#endif
+
+#include
+
+#if defined(POLARSSL_MD2_C)
+
+static void md2_starts_wrap( void *ctx )
+{
+ md2_starts( (md2_context *) ctx );
+}
+
+static void md2_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ md2_update( (md2_context *) ctx, input, ilen );
+}
+
+static void md2_finish_wrap( void *ctx, unsigned char *output )
+{
+ md2_finish( (md2_context *) ctx, output );
+}
+
+int md2_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return md2_file( path, output );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void md2_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ md2_hmac_starts( (md2_context *) ctx, key, keylen );
+}
+
+static void md2_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ md2_hmac_update( (md2_context *) ctx, input, ilen );
+}
+
+static void md2_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ md2_hmac_finish( (md2_context *) ctx, output );
+}
+
+static void md2_hmac_reset_wrap( void *ctx )
+{
+ md2_hmac_reset( (md2_context *) ctx );
+}
+
+static void * md2_ctx_alloc( void )
+{
+ return malloc( sizeof( md2_context ) );
+}
+
+static void md2_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t md2_info = {
+ POLARSSL_MD_MD2,
+ "MD2",
+ 16,
+ md2_starts_wrap,
+ md2_update_wrap,
+ md2_finish_wrap,
+ md2,
+ md2_file_wrap,
+ md2_hmac_starts_wrap,
+ md2_hmac_update_wrap,
+ md2_hmac_finish_wrap,
+ md2_hmac_reset_wrap,
+ md2_hmac,
+ md2_ctx_alloc,
+ md2_ctx_free,
+};
+
+#endif
+
+#if defined(POLARSSL_MD4_C)
+
+void md4_starts_wrap( void *ctx )
+{
+ md4_starts( (md4_context *) ctx );
+}
+
+void md4_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ md4_update( (md4_context *) ctx, input, ilen );
+}
+
+void md4_finish_wrap( void *ctx, unsigned char *output )
+{
+ md4_finish( (md4_context *) ctx, output );
+}
+
+int md4_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return md4_file( path, output );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void md4_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ md4_hmac_starts( (md4_context *) ctx, key, keylen );
+}
+
+void md4_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ md4_hmac_update( (md4_context *) ctx, input, ilen );
+}
+
+void md4_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ md4_hmac_finish( (md4_context *) ctx, output );
+}
+
+void md4_hmac_reset_wrap( void *ctx )
+{
+ md4_hmac_reset( (md4_context *) ctx );
+}
+
+void *md4_ctx_alloc( void )
+{
+ return malloc( sizeof( md4_context ) );
+}
+
+void md4_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t md4_info = {
+ POLARSSL_MD_MD4,
+ "MD4",
+ 16,
+ md4_starts_wrap,
+ md4_update_wrap,
+ md4_finish_wrap,
+ md4,
+ md4_file_wrap,
+ md4_hmac_starts_wrap,
+ md4_hmac_update_wrap,
+ md4_hmac_finish_wrap,
+ md4_hmac_reset_wrap,
+ md4_hmac,
+ md4_ctx_alloc,
+ md4_ctx_free,
+};
+
+#endif
+
+#if defined(POLARSSL_MD5_C)
+
+static void md5_starts_wrap( void *ctx )
+{
+ md5_starts( (md5_context *) ctx );
+}
+
+static void md5_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ md5_update( (md5_context *) ctx, input, ilen );
+}
+
+static void md5_finish_wrap( void *ctx, unsigned char *output )
+{
+ md5_finish( (md5_context *) ctx, output );
+}
+
+int md5_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return md5_file( path, output );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void md5_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ md5_hmac_starts( (md5_context *) ctx, key, keylen );
+}
+
+static void md5_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ md5_hmac_update( (md5_context *) ctx, input, ilen );
+}
+
+static void md5_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ md5_hmac_finish( (md5_context *) ctx, output );
+}
+
+static void md5_hmac_reset_wrap( void *ctx )
+{
+ md5_hmac_reset( (md5_context *) ctx );
+}
+
+static void * md5_ctx_alloc( void )
+{
+ return malloc( sizeof( md5_context ) );
+}
+
+static void md5_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t md5_info = {
+ POLARSSL_MD_MD5,
+ "MD5",
+ 16,
+ md5_starts_wrap,
+ md5_update_wrap,
+ md5_finish_wrap,
+ md5,
+ md5_file_wrap,
+ md5_hmac_starts_wrap,
+ md5_hmac_update_wrap,
+ md5_hmac_finish_wrap,
+ md5_hmac_reset_wrap,
+ md5_hmac,
+ md5_ctx_alloc,
+ md5_ctx_free,
+};
+
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+
+void sha1_starts_wrap( void *ctx )
+{
+ sha1_starts( (sha1_context *) ctx );
+}
+
+void sha1_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha1_update( (sha1_context *) ctx, input, ilen );
+}
+
+void sha1_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha1_finish( (sha1_context *) ctx, output );
+}
+
+int sha1_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return sha1_file( path, output );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha1_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ sha1_hmac_starts( (sha1_context *) ctx, key, keylen );
+}
+
+void sha1_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha1_hmac_update( (sha1_context *) ctx, input, ilen );
+}
+
+void sha1_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha1_hmac_finish( (sha1_context *) ctx, output );
+}
+
+void sha1_hmac_reset_wrap( void *ctx )
+{
+ sha1_hmac_reset( (sha1_context *) ctx );
+}
+
+void * sha1_ctx_alloc( void )
+{
+ return malloc( sizeof( sha1_context ) );
+}
+
+void sha1_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t sha1_info = {
+ POLARSSL_MD_SHA1,
+ "SHA1",
+ 20,
+ sha1_starts_wrap,
+ sha1_update_wrap,
+ sha1_finish_wrap,
+ sha1,
+ sha1_file_wrap,
+ sha1_hmac_starts_wrap,
+ sha1_hmac_update_wrap,
+ sha1_hmac_finish_wrap,
+ sha1_hmac_reset_wrap,
+ sha1_hmac,
+ sha1_ctx_alloc,
+ sha1_ctx_free,
+};
+
+#endif
+
+/*
+ * Wrappers for generic message digests
+ */
+#if defined(POLARSSL_SHA2_C)
+
+void sha224_starts_wrap( void *ctx )
+{
+ sha2_starts( (sha2_context *) ctx, 1 );
+}
+
+void sha224_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha2_update( (sha2_context *) ctx, input, ilen );
+}
+
+void sha224_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha2_finish( (sha2_context *) ctx, output );
+}
+
+void sha224_wrap( const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha2( input, ilen, output, 1 );
+}
+
+int sha224_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return sha2_file( path, output, 1 );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha224_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ sha2_hmac_starts( (sha2_context *) ctx, key, keylen, 1 );
+}
+
+void sha224_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha2_hmac_update( (sha2_context *) ctx, input, ilen );
+}
+
+void sha224_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha2_hmac_finish( (sha2_context *) ctx, output );
+}
+
+void sha224_hmac_reset_wrap( void *ctx )
+{
+ sha2_hmac_reset( (sha2_context *) ctx );
+}
+
+void sha224_hmac_wrap( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha2_hmac( key, keylen, input, ilen, output, 1 );
+}
+
+void * sha224_ctx_alloc( void )
+{
+ return malloc( sizeof( sha2_context ) );
+}
+
+void sha224_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t sha224_info = {
+ POLARSSL_MD_SHA224,
+ "SHA224",
+ 28,
+ sha224_starts_wrap,
+ sha224_update_wrap,
+ sha224_finish_wrap,
+ sha224_wrap,
+ sha224_file_wrap,
+ sha224_hmac_starts_wrap,
+ sha224_hmac_update_wrap,
+ sha224_hmac_finish_wrap,
+ sha224_hmac_reset_wrap,
+ sha224_hmac_wrap,
+ sha224_ctx_alloc,
+ sha224_ctx_free,
+};
+
+void sha256_starts_wrap( void *ctx )
+{
+ sha2_starts( (sha2_context *) ctx, 0 );
+}
+
+void sha256_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha2_update( (sha2_context *) ctx, input, ilen );
+}
+
+void sha256_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha2_finish( (sha2_context *) ctx, output );
+}
+
+void sha256_wrap( const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha2( input, ilen, output, 0 );
+}
+
+int sha256_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return sha2_file( path, output, 0 );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha256_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ sha2_hmac_starts( (sha2_context *) ctx, key, keylen, 0 );
+}
+
+void sha256_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha2_hmac_update( (sha2_context *) ctx, input, ilen );
+}
+
+void sha256_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha2_hmac_finish( (sha2_context *) ctx, output );
+}
+
+void sha256_hmac_reset_wrap( void *ctx )
+{
+ sha2_hmac_reset( (sha2_context *) ctx );
+}
+
+void sha256_hmac_wrap( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha2_hmac( key, keylen, input, ilen, output, 0 );
+}
+
+void * sha256_ctx_alloc( void )
+{
+ return malloc( sizeof( sha2_context ) );
+}
+
+void sha256_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t sha256_info = {
+ POLARSSL_MD_SHA256,
+ "SHA256",
+ 32,
+ sha256_starts_wrap,
+ sha256_update_wrap,
+ sha256_finish_wrap,
+ sha256_wrap,
+ sha256_file_wrap,
+ sha256_hmac_starts_wrap,
+ sha256_hmac_update_wrap,
+ sha256_hmac_finish_wrap,
+ sha256_hmac_reset_wrap,
+ sha256_hmac_wrap,
+ sha256_ctx_alloc,
+ sha256_ctx_free,
+};
+
+#endif
+
+#if defined(POLARSSL_SHA4_C)
+
+void sha384_starts_wrap( void *ctx )
+{
+ sha4_starts( (sha4_context *) ctx, 1 );
+}
+
+void sha384_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha4_update( (sha4_context *) ctx, input, ilen );
+}
+
+void sha384_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha4_finish( (sha4_context *) ctx, output );
+}
+
+void sha384_wrap( const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha4( input, ilen, output, 1 );
+}
+
+int sha384_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return sha4_file( path, output, 1 );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha384_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ sha4_hmac_starts( (sha4_context *) ctx, key, keylen, 1 );
+}
+
+void sha384_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha4_hmac_update( (sha4_context *) ctx, input, ilen );
+}
+
+void sha384_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha4_hmac_finish( (sha4_context *) ctx, output );
+}
+
+void sha384_hmac_reset_wrap( void *ctx )
+{
+ sha4_hmac_reset( (sha4_context *) ctx );
+}
+
+void sha384_hmac_wrap( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha4_hmac( key, keylen, input, ilen, output, 1 );
+}
+
+void * sha384_ctx_alloc( void )
+{
+ return malloc( sizeof( sha4_context ) );
+}
+
+void sha384_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t sha384_info = {
+ POLARSSL_MD_SHA384,
+ "SHA384",
+ 48,
+ sha384_starts_wrap,
+ sha384_update_wrap,
+ sha384_finish_wrap,
+ sha384_wrap,
+ sha384_file_wrap,
+ sha384_hmac_starts_wrap,
+ sha384_hmac_update_wrap,
+ sha384_hmac_finish_wrap,
+ sha384_hmac_reset_wrap,
+ sha384_hmac_wrap,
+ sha384_ctx_alloc,
+ sha384_ctx_free,
+};
+
+void sha512_starts_wrap( void *ctx )
+{
+ sha4_starts( (sha4_context *) ctx, 0 );
+}
+
+void sha512_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha4_update( (sha4_context *) ctx, input, ilen );
+}
+
+void sha512_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha4_finish( (sha4_context *) ctx, output );
+}
+
+void sha512_wrap( const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha4( input, ilen, output, 0 );
+}
+
+int sha512_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return sha4_file( path, output, 0 );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha512_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ sha4_hmac_starts( (sha4_context *) ctx, key, keylen, 0 );
+}
+
+void sha512_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha4_hmac_update( (sha4_context *) ctx, input, ilen );
+}
+
+void sha512_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha4_hmac_finish( (sha4_context *) ctx, output );
+}
+
+void sha512_hmac_reset_wrap( void *ctx )
+{
+ sha4_hmac_reset( (sha4_context *) ctx );
+}
+
+void sha512_hmac_wrap( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha4_hmac( key, keylen, input, ilen, output, 0 );
+}
+
+void * sha512_ctx_alloc( void )
+{
+ return malloc( sizeof( sha4_context ) );
+}
+
+void sha512_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t sha512_info = {
+ POLARSSL_MD_SHA512,
+ "SHA512",
+ 64,
+ sha512_starts_wrap,
+ sha512_update_wrap,
+ sha512_finish_wrap,
+ sha512_wrap,
+ sha512_file_wrap,
+ sha512_hmac_starts_wrap,
+ sha512_hmac_update_wrap,
+ sha512_hmac_finish_wrap,
+ sha512_hmac_reset_wrap,
+ sha512_hmac_wrap,
+ sha512_ctx_alloc,
+ sha512_ctx_free,
+};
+
+#endif
+
+#endif
diff --git a/polarssl/md_wrap.h b/polarssl/md_wrap.h
new file mode 100644
index 0000000..43fc76f
--- /dev/null
+++ b/polarssl/md_wrap.h
@@ -0,0 +1,64 @@
+/**
+ * \file md_wrap.h
+ *
+ * \brief Message digest wrappers.
+ *
+ * \author Adriaan de Jong
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD_WRAP_H
+#define POLARSSL_MD_WRAP_H
+
+#include "polarssl/config.h"
+#include "polarssl/md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(POLARSSL_MD2_C)
+extern const md_info_t md2_info;
+#endif
+#if defined(POLARSSL_MD4_C)
+extern const md_info_t md4_info;
+#endif
+#if defined(POLARSSL_MD5_C)
+extern const md_info_t md5_info;
+#endif
+#if defined(POLARSSL_SHA1_C)
+extern const md_info_t sha1_info;
+#endif
+#if defined(POLARSSL_SHA2_C)
+extern const md_info_t sha224_info;
+extern const md_info_t sha256_info;
+#endif
+#if defined(POLARSSL_SHA4_C)
+extern const md_info_t sha384_info;
+extern const md_info_t sha512_info;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_MD_WRAP_H */
diff --git a/polarssl/net.c b/polarssl/net.c
new file mode 100644
index 0000000..7a1818d
--- /dev/null
+++ b/polarssl/net.c
@@ -0,0 +1,374 @@
+/*
+ * TCP networking functions
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_NET_C)
+
+#include "polarssl/net.h"
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+
+#include
+#include
+
+#if defined(_WIN32_WCE)
+#pragma comment( lib, "ws2.lib" )
+#else
+#pragma comment( lib, "ws2_32.lib" )
+#endif
+
+#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0)
+#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0)
+#define close(fd) closesocket(fd)
+
+static int wsa_init_done = 0;
+
+#else
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \
+ defined(__DragonflyBSD__)
+#include
+#elif defined(__APPLE__)
+#include
+#elif defined(sun)
+#include
+#else
+#include
+#endif
+
+#endif
+
+#include
+#include
+#include
+
+#ifdef _MSC_VER
+#include
+typedef UINT32 uint32_t;
+#else
+#include
+#endif
+
+/*
+ * htons() is not always available.
+ * By default go for LITTLE_ENDIAN variant. Otherwise hope for _BYTE_ORDER and __BIG_ENDIAN
+ * to help determine endianess.
+ */
+#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN
+#define POLARSSL_HTONS(n) (n)
+#define POLARSSL_HTONL(n) (n)
+#else
+#define POLARSSL_HTONS(n) ((((unsigned short)(n) & 0xFF ) << 8 ) | \
+ (((unsigned short)(n) & 0xFF00 ) >> 8 ))
+#define POLARSSL_HTONL(n) ((((unsigned long )(n) & 0xFF ) << 24) | \
+ (((unsigned long )(n) & 0xFF00 ) << 8 ) | \
+ (((unsigned long )(n) & 0xFF0000 ) >> 8 ) | \
+ (((unsigned long )(n) & 0xFF000000) >> 24))
+#endif
+
+unsigned short net_htons(unsigned short n);
+unsigned long net_htonl(unsigned long n);
+#define net_htons(n) POLARSSL_HTONS(n)
+#define net_htonl(n) POLARSSL_HTONL(n)
+
+/*
+ * Initiate a TCP connection with host:port
+ */
+int net_connect( int *fd, const char *host, int port )
+{
+ struct sockaddr_in server_addr;
+ struct hostent *server_host;
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ WSADATA wsaData;
+
+ if( wsa_init_done == 0 )
+ {
+ if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
+ return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+ wsa_init_done = 1;
+ }
+#else
+ signal( SIGPIPE, SIG_IGN );
+#endif
+
+ if( ( server_host = gethostbyname( host ) ) == NULL )
+ return( POLARSSL_ERR_NET_UNKNOWN_HOST );
+
+ if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
+ return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+ memcpy( (void *) &server_addr.sin_addr,
+ (void *) server_host->h_addr,
+ server_host->h_length );
+
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = net_htons( port );
+
+ if( connect( *fd, (struct sockaddr *) &server_addr,
+ sizeof( server_addr ) ) < 0 )
+ {
+ close( *fd );
+ return( POLARSSL_ERR_NET_CONNECT_FAILED );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Create a listening socket on bind_ip:port
+ */
+int net_bind( int *fd, const char *bind_ip, int port )
+{
+ int n, c[4];
+ struct sockaddr_in server_addr;
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ WSADATA wsaData;
+
+ if( wsa_init_done == 0 )
+ {
+ if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
+ return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+ wsa_init_done = 1;
+ }
+#else
+ signal( SIGPIPE, SIG_IGN );
+#endif
+
+ if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
+ return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+ n = 1;
+ setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
+ (const char *) &n, sizeof( n ) );
+
+ server_addr.sin_addr.s_addr = net_htonl( INADDR_ANY );
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = net_htons( port );
+
+ if( bind_ip != NULL )
+ {
+ memset( c, 0, sizeof( c ) );
+ sscanf( bind_ip, "%d.%d.%d.%d", &c[0], &c[1], &c[2], &c[3] );
+
+ for( n = 0; n < 4; n++ )
+ if( c[n] < 0 || c[n] > 255 )
+ break;
+
+ if( n == 4 )
+ server_addr.sin_addr.s_addr = net_htonl(
+ ( (uint32_t) c[0] << 24 ) |
+ ( (uint32_t) c[1] << 16 ) |
+ ( (uint32_t) c[2] << 8 ) |
+ ( (uint32_t) c[3] ) );
+ }
+
+ if( bind( *fd, (struct sockaddr *) &server_addr,
+ sizeof( server_addr ) ) < 0 )
+ {
+ close( *fd );
+ return( POLARSSL_ERR_NET_BIND_FAILED );
+ }
+
+ if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 )
+ {
+ close( *fd );
+ return( POLARSSL_ERR_NET_LISTEN_FAILED );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Check if the current operation is blocking
+ */
+static int net_is_blocking( void )
+{
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ return( WSAGetLastError() == WSAEWOULDBLOCK );
+#else
+ switch( errno )
+ {
+#if defined EAGAIN
+ case EAGAIN:
+#endif
+#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ return( 1 );
+ }
+ return( 0 );
+#endif
+}
+
+/*
+ * Accept a connection from a remote client
+ */
+int net_accept( int bind_fd, int *client_fd, void *client_ip )
+{
+ struct sockaddr_in client_addr;
+
+#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
+ defined(_SOCKLEN_T_DECLARED)
+ socklen_t n = (socklen_t) sizeof( client_addr );
+#else
+ int n = (int) sizeof( client_addr );
+#endif
+
+ *client_fd = accept( bind_fd, (struct sockaddr *)
+ &client_addr, &n );
+
+ if( *client_fd < 0 )
+ {
+ if( net_is_blocking() != 0 )
+ return( POLARSSL_ERR_NET_WANT_READ );
+
+ return( POLARSSL_ERR_NET_ACCEPT_FAILED );
+ }
+
+ if( client_ip != NULL )
+ memcpy( client_ip, &client_addr.sin_addr.s_addr,
+ sizeof( client_addr.sin_addr.s_addr ) );
+
+ return( 0 );
+}
+
+/*
+ * Set the socket blocking or non-blocking
+ */
+int net_set_block( int fd )
+{
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ u_long n = 0;
+ return( ioctlsocket( fd, FIONBIO, &n ) );
+#else
+ return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) & ~O_NONBLOCK ) );
+#endif
+}
+
+int net_set_nonblock( int fd )
+{
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ u_long n = 1;
+ return( ioctlsocket( fd, FIONBIO, &n ) );
+#else
+ return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) );
+#endif
+}
+
+/*
+ * Portable usleep helper
+ */
+void net_usleep( unsigned long usec )
+{
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = usec;
+ select( 0, NULL, NULL, NULL, &tv );
+}
+
+/*
+ * Read at most 'len' characters
+ */
+int net_recv( void *ctx, unsigned char *buf, size_t len )
+{
+ int ret = read( *((int *) ctx), buf, len );
+
+ if( ret < 0 )
+ {
+ if( net_is_blocking() != 0 )
+ return( POLARSSL_ERR_NET_WANT_READ );
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ if( WSAGetLastError() == WSAECONNRESET )
+ return( POLARSSL_ERR_NET_CONN_RESET );
+#else
+ if( errno == EPIPE || errno == ECONNRESET )
+ return( POLARSSL_ERR_NET_CONN_RESET );
+
+ if( errno == EINTR )
+ return( POLARSSL_ERR_NET_WANT_READ );
+#endif
+
+ return( POLARSSL_ERR_NET_RECV_FAILED );
+ }
+
+ return( ret );
+}
+
+/*
+ * Write at most 'len' characters
+ */
+int net_send( void *ctx, const unsigned char *buf, size_t len )
+{
+ int ret = write( *((int *) ctx), buf, len );
+
+ if( ret < 0 )
+ {
+ if( net_is_blocking() != 0 )
+ return( POLARSSL_ERR_NET_WANT_WRITE );
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ if( WSAGetLastError() == WSAECONNRESET )
+ return( POLARSSL_ERR_NET_CONN_RESET );
+#else
+ if( errno == EPIPE || errno == ECONNRESET )
+ return( POLARSSL_ERR_NET_CONN_RESET );
+
+ if( errno == EINTR )
+ return( POLARSSL_ERR_NET_WANT_WRITE );
+#endif
+
+ return( POLARSSL_ERR_NET_SEND_FAILED );
+ }
+
+ return( ret );
+}
+
+/*
+ * Gracefully close the connection
+ */
+void net_close( int fd )
+{
+ shutdown( fd, 2 );
+ close( fd );
+}
+
+#endif
diff --git a/polarssl/net.h b/polarssl/net.h
new file mode 100644
index 0000000..88302ac
--- /dev/null
+++ b/polarssl/net.h
@@ -0,0 +1,159 @@
+/**
+ * \file net.h
+ *
+ * \brief Network communication functions
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_NET_H
+#define POLARSSL_NET_H
+
+#include
+
+#define POLARSSL_ERR_NET_UNKNOWN_HOST -0x0056 /**< Failed to get an IP address for the given hostname. */
+#define POLARSSL_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */
+#define POLARSSL_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */
+#define POLARSSL_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */
+#define POLARSSL_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */
+#define POLARSSL_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */
+#define POLARSSL_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */
+#define POLARSSL_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */
+#define POLARSSL_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */
+#define POLARSSL_ERR_NET_WANT_READ -0x0052 /**< Connection requires a read call. */
+#define POLARSSL_ERR_NET_WANT_WRITE -0x0054 /**< Connection requires a write call. */
+
+#define POLARSSL_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Initiate a TCP connection with host:port
+ *
+ * \param fd Socket to use
+ * \param host Host to connect to
+ * \param port Port to connect to
+ *
+ * \return 0 if successful, or one of:
+ * POLARSSL_ERR_NET_SOCKET_FAILED,
+ * POLARSSL_ERR_NET_UNKNOWN_HOST,
+ * POLARSSL_ERR_NET_CONNECT_FAILED
+ */
+int net_connect( int *fd, const char *host, int port );
+
+/**
+ * \brief Create a listening socket on bind_ip:port.
+ * If bind_ip == NULL, all interfaces are binded.
+ *
+ * \param fd Socket to use
+ * \param bind_ip IP to bind to, can be NULL
+ * \param port Port number to use
+ *
+ * \return 0 if successful, or one of:
+ * POLARSSL_ERR_NET_SOCKET_FAILED,
+ * POLARSSL_ERR_NET_BIND_FAILED,
+ * POLARSSL_ERR_NET_LISTEN_FAILED
+ */
+int net_bind( int *fd, const char *bind_ip, int port );
+
+/**
+ * \brief Accept a connection from a remote client
+ *
+ * \param bind_fd Relevant socket
+ * \param client_fd Will contain the connected client socket
+ * \param client_ip Will contain the client IP address
+ *
+ * \return 0 if successful, POLARSSL_ERR_NET_ACCEPT_FAILED, or
+ * POLARSSL_ERR_NET_WOULD_BLOCK is bind_fd was set to
+ * non-blocking and accept() is blocking.
+ */
+int net_accept( int bind_fd, int *client_fd, void *client_ip );
+
+/**
+ * \brief Set the socket blocking
+ *
+ * \param fd Socket to set
+ *
+ * \return 0 if successful, or a non-zero error code
+ */
+int net_set_block( int fd );
+
+/**
+ * \brief Set the socket non-blocking
+ *
+ * \param fd Socket to set
+ *
+ * \return 0 if successful, or a non-zero error code
+ */
+int net_set_nonblock( int fd );
+
+/**
+ * \brief Portable usleep helper
+ *
+ * \param usec Amount of microseconds to sleep
+ *
+ * \note Real amount of time slept will not be less than
+ * select()'s timeout granularity (typically, 10ms).
+ */
+void net_usleep( unsigned long usec );
+
+/**
+ * \brief Read at most 'len' characters. If no error occurs,
+ * the actual amount read is returned.
+ *
+ * \param ctx Socket
+ * \param buf The buffer to write to
+ * \param len Maximum length of the buffer
+ *
+ * \return This function returns the number of bytes received,
+ * or a non-zero error code; POLARSSL_ERR_NET_WANT_READ
+ * indicates read() is blocking.
+ */
+int net_recv( void *ctx, unsigned char *buf, size_t len );
+
+/**
+ * \brief Write at most 'len' characters. If no error occurs,
+ * the actual amount read is returned.
+ *
+ * \param ctx Socket
+ * \param buf The buffer to read from
+ * \param len The length of the buffer
+ *
+ * \return This function returns the number of bytes sent,
+ * or a non-zero error code; POLARSSL_ERR_NET_WANT_WRITE
+ * indicates write() is blocking.
+ */
+int net_send( void *ctx, const unsigned char *buf, size_t len );
+
+/**
+ * \brief Gracefully shutdown the connection
+ *
+ * \param fd The socket to close
+ */
+void net_close( int fd );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* net.h */
diff --git a/polarssl/openssl.h b/polarssl/openssl.h
new file mode 100644
index 0000000..4423857
--- /dev/null
+++ b/polarssl/openssl.h
@@ -0,0 +1,136 @@
+/**
+ * \file openssl.h
+ *
+ * \brief OpenSSL wrapper (definitions, inline functions).
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * OpenSSL wrapper contributed by David Barett
+ */
+#ifndef POLARSSL_OPENSSL_H
+#define POLARSSL_OPENSSL_H
+
+#include "polarssl/aes.h"
+#include "polarssl/md5.h"
+#include "polarssl/rsa.h"
+#include "polarssl/sha1.h"
+
+#define AES_SIZE 16
+#define AES_BLOCK_SIZE 16
+#define AES_KEY aes_context
+#define MD5_CTX md5_context
+#define SHA_CTX sha1_context
+
+#define SHA1_Init( CTX ) \
+ sha1_starts( (CTX) )
+#define SHA1_Update( CTX, BUF, LEN ) \
+ sha1_update( (CTX), (unsigned char *)(BUF), (LEN) )
+#define SHA1_Final( OUT, CTX ) \
+ sha1_finish( (CTX), (OUT) )
+
+#define MD5_Init( CTX ) \
+ md5_starts( (CTX) )
+#define MD5_Update( CTX, BUF, LEN ) \
+ md5_update( (CTX), (unsigned char *)(BUF), (LEN) )
+#define MD5_Final( OUT, CTX ) \
+ md5_finish( (CTX), (OUT) )
+
+#define AES_set_encrypt_key( KEY, KEYSIZE, CTX ) \
+ aes_setkey_enc( (CTX), (KEY), (KEYSIZE) )
+#define AES_set_decrypt_key( KEY, KEYSIZE, CTX ) \
+ aes_setkey_dec( (CTX), (KEY), (KEYSIZE) )
+#define AES_cbc_encrypt( INPUT, OUTPUT, LEN, CTX, IV, MODE ) \
+ aes_crypt_cbc( (CTX), (MODE), (LEN), (IV), (INPUT), (OUTPUT) )
+
+/*
+ * RSA stuff follows. TODO: needs cleanup
+ */
+inline int __RSA_Passthrough( void *output, void *input, int size )
+{
+ memcpy( output, input, size );
+ return size;
+}
+
+inline rsa_context* d2i_RSA_PUBKEY( void *ignore, unsigned char **bufptr,
+ int len )
+{
+ unsigned char *buffer = *(unsigned char **) bufptr;
+ rsa_context *rsa;
+
+ /*
+ * Not a general-purpose parser: only parses public key from *exactly*
+ * openssl genrsa -out privkey.pem 512 (or 1024)
+ * openssl rsa -in privkey.pem -out privatekey.der -outform der
+ * openssl rsa -in privkey.pem -out pubkey.der -outform der -pubout
+ *
+ * TODO: make a general-purpose parse
+ */
+ if( ignore != 0 || ( len != 94 && len != 162 ) )
+ return( 0 );
+
+ rsa = (rsa_context *) malloc( sizeof( rsa_rsa ) );
+ if( rsa == NULL )
+ return( 0 );
+
+ memset( rsa, 0, sizeof( rsa_context ) );
+
+ if( ( len == 94 &&
+ mpi_read_binary( &rsa->N, &buffer[ 25], 64 ) == 0 &&
+ mpi_read_binary( &rsa->E, &buffer[ 91], 3 ) == 0 ) ||
+ ( len == 162 &&
+ mpi_read_binary( &rsa->N, &buffer[ 29], 128 ) == 0 ) &&
+ mpi_read_binary( &rsa->E, &buffer[159], 3 ) == 0 )
+ {
+ /*
+ * key read successfully
+ */
+ rsa->len = ( mpi_msb( &rsa->N ) + 7 ) >> 3;
+ return( rsa );
+ }
+ else
+ {
+ memset( rsa, 0, sizeof( rsa_context ) );
+ free( rsa );
+ return( 0 );
+ }
+}
+
+#define RSA rsa_context
+#define RSA_PKCS1_PADDING 1 /* ignored; always encrypt with this */
+#define RSA_size( CTX ) (CTX)->len
+#define RSA_free( CTX ) rsa_free( CTX )
+#define ERR_get_error( ) "ERR_get_error() not supported"
+#define RSA_blinding_off( IGNORE )
+
+#define d2i_RSAPrivateKey( a, b, c ) new rsa_context /* TODO: C++ bleh */
+
+inline int RSA_public_decrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PUBLIC, &outsize, input, output ) ) return outsize; else return -1; }
+inline int RSA_private_decrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PRIVATE, &outsize, input, output ) ) return outsize; else return -1; }
+inline int RSA_public_encrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PUBLIC, size, input, output ) ) return RSA_size(key); else return -1; }
+inline int RSA_private_encrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PRIVATE, size, input, output ) ) return RSA_size(key); else return -1; }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* openssl.h */
diff --git a/polarssl/padlock.c b/polarssl/padlock.c
new file mode 100644
index 0000000..9ddac15
--- /dev/null
+++ b/polarssl/padlock.c
@@ -0,0 +1,162 @@
+/*
+ * VIA PadLock support functions
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * This implementation is based on the VIA PadLock Programming Guide:
+ *
+ * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/
+ * programming_guide.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_PADLOCK_C)
+
+#include "polarssl/padlock.h"
+
+#if defined(POLARSSL_HAVE_X86)
+
+/*
+ * PadLock detection routine
+ */
+int padlock_supports( int feature )
+{
+ static int flags = -1;
+ int ebx, edx;
+
+ if( flags == -1 )
+ {
+ __asm__( "movl %%ebx, %0 \n" \
+ "movl $0xC0000000, %%eax \n" \
+ "cpuid \n" \
+ "cmpl $0xC0000001, %%eax \n" \
+ "movl $0, %%edx \n" \
+ "jb unsupported \n" \
+ "movl $0xC0000001, %%eax \n" \
+ "cpuid \n" \
+ "unsupported: \n" \
+ "movl %%edx, %1 \n" \
+ "movl %2, %%ebx \n"
+ : "=m" (ebx), "=m" (edx)
+ : "m" (ebx)
+ : "eax", "ecx", "edx" );
+
+ flags = edx;
+ }
+
+ return( flags & feature );
+}
+
+/*
+ * PadLock AES-ECB block en(de)cryption
+ */
+int padlock_xcryptecb( aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ int ebx;
+ uint32_t *rk;
+ uint32_t *blk;
+ uint32_t *ctrl;
+ unsigned char buf[256];
+
+ rk = ctx->rk;
+ blk = PADLOCK_ALIGN16( buf );
+ memcpy( blk, input, 16 );
+
+ ctrl = blk + 4;
+ *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 );
+
+ __asm__( "pushfl; popfl \n" \
+ "movl %%ebx, %0 \n" \
+ "movl $1, %%ecx \n" \
+ "movl %2, %%edx \n" \
+ "movl %3, %%ebx \n" \
+ "movl %4, %%esi \n" \
+ "movl %4, %%edi \n" \
+ ".byte 0xf3,0x0f,0xa7,0xc8\n" \
+ "movl %1, %%ebx \n"
+ : "=m" (ebx)
+ : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk)
+ : "ecx", "edx", "esi", "edi" );
+
+ memcpy( output, blk, 16 );
+
+ return( 0 );
+}
+
+/*
+ * PadLock AES-CBC buffer en(de)cryption
+ */
+int padlock_xcryptcbc( aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ebx;
+ size_t count;
+ uint32_t *rk;
+ uint32_t *iw;
+ uint32_t *ctrl;
+ unsigned char buf[256];
+
+ if( ( (long) input & 15 ) != 0 ||
+ ( (long) output & 15 ) != 0 )
+ return( POLARSSL_ERR_PADLOCK_DATA_MISALIGNED );
+
+ rk = ctx->rk;
+ iw = PADLOCK_ALIGN16( buf );
+ memcpy( iw, iv, 16 );
+
+ ctrl = iw + 4;
+ *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + (mode^1) - 10 ) << 9 );
+
+ count = (length + 15) >> 4;
+
+ __asm__( "pushfl; popfl \n" \
+ "movl %%ebx, %0 \n" \
+ "movl %2, %%ecx \n" \
+ "movl %3, %%edx \n" \
+ "movl %4, %%ebx \n" \
+ "movl %5, %%esi \n" \
+ "movl %6, %%edi \n" \
+ "movl %7, %%eax \n" \
+ ".byte 0xf3,0x0f,0xa7,0xd0\n" \
+ "movl %1, %%ebx \n"
+ : "=m" (ebx)
+ : "m" (ebx), "m" (count), "m" (ctrl),
+ "m" (rk), "m" (input), "m" (output), "m" (iw)
+ : "eax", "ecx", "edx", "esi", "edi" );
+
+ memcpy( iv, iw, 16 );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/padlock.h b/polarssl/padlock.h
new file mode 100644
index 0000000..48f5f62
--- /dev/null
+++ b/polarssl/padlock.h
@@ -0,0 +1,108 @@
+/**
+ * \file padlock.h
+ *
+ * \brief VIA PadLock ACE for HW encryption/decryption supported by some processors
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PADLOCK_H
+#define POLARSSL_PADLOCK_H
+
+#include "polarssl/aes.h"
+
+#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */
+
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__)
+
+#ifndef POLARSSL_HAVE_X86
+#define POLARSSL_HAVE_X86
+#endif
+
+#ifdef _MSC_VER
+#include
+typedef INT32 int32_t;
+#else
+#include
+#endif
+
+
+#define PADLOCK_RNG 0x000C
+#define PADLOCK_ACE 0x00C0
+#define PADLOCK_PHE 0x0C00
+#define PADLOCK_PMM 0x3000
+
+#define PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) x & ~15))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief PadLock detection routine
+ *
+ * \param The feature to detect
+ *
+ * \return 1 if CPU has support for the feature, 0 otherwise
+ */
+int padlock_supports( int feature );
+
+/**
+ * \brief PadLock AES-ECB block en(de)cryption
+ *
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param input 16-byte input block
+ * \param output 16-byte output block
+ *
+ * \return 0 if success, 1 if operation failed
+ */
+int padlock_xcryptecb( aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+/**
+ * \brief PadLock AES-CBC buffer en(de)cryption
+ *
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if success, 1 if operation failed
+ */
+int padlock_xcryptcbc( aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAVE_X86 */
+
+#endif /* padlock.h */
diff --git a/polarssl/pbkdf2.c b/polarssl/pbkdf2.c
new file mode 100644
index 0000000..09e56df
--- /dev/null
+++ b/polarssl/pbkdf2.c
@@ -0,0 +1,60 @@
+/**
+ * \file pbkdf2.c
+ *
+ * \brief Password-Based Key Derivation Function 2 (from PKCS#5)
+ * DEPRECATED: Use pkcs5.c instead
+ *
+ * \author Mathias Olsson
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * PBKDF2 is part of PKCS#5
+ *
+ * http://tools.ietf.org/html/rfc2898 (Specification)
+ * http://tools.ietf.org/html/rfc6070 (Test vectors)
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_PBKDF2_C)
+
+#include "polarssl/pbkdf2.h"
+#include "polarssl/pkcs5.h"
+
+int pbkdf2_hmac( md_context_t *ctx, const unsigned char *password, size_t plen,
+ const unsigned char *salt, size_t slen,
+ unsigned int iteration_count,
+ uint32_t key_length, unsigned char *output )
+{
+ return pkcs5_pbkdf2_hmac( ctx, password, plen, salt, slen, iteration_count,
+ key_length, output );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+int pbkdf2_self_test( int verbose )
+{
+ return pkcs5_self_test( verbose );
+}
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_PBKDF2_C */
diff --git a/polarssl/pbkdf2.h b/polarssl/pbkdf2.h
new file mode 100644
index 0000000..2a1f4ba
--- /dev/null
+++ b/polarssl/pbkdf2.h
@@ -0,0 +1,82 @@
+/**
+ * \file pbkdf2.h
+ *
+ * \brief Password-Based Key Derivation Function 2 (from PKCS#5)
+ * DEPRECATED: use pkcs5.h instead.
+ *
+ * \author Mathias Olsson
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PBKDF2_H
+#define POLARSSL_PBKDF2_H
+
+#include
+
+#include "polarssl/md.h"
+
+#ifdef _MSC_VER
+#include
+typedef UINT32 uint32_t;
+#else
+#include
+#endif
+
+#define POLARSSL_ERR_PBKDF2_BAD_INPUT_DATA -0x007C /**< Bad input parameters to function. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief PKCS#5 PBKDF2 using HMAC
+ * DEPRECATED: Use pkcs5_pbkdf2_hmac() instead!
+ *
+ * \param ctx Generic HMAC context
+ * \param password Password to use when generating key
+ * \param plen Length of password
+ * \param salt Salt to use when generating key
+ * \param slen Length of salt
+ * \param iteration_count Iteration count
+ * \param key_length Length of generated key
+ * \param output Generated key. Must be at least as big as key_length
+ *
+ * \returns 0 on success, or a PolarSSL error code if verification fails.
+ */
+int pbkdf2_hmac( md_context_t *ctx, const unsigned char *password,
+ size_t plen, const unsigned char *salt, size_t slen,
+ unsigned int iteration_count,
+ uint32_t key_length, unsigned char *output );
+
+/**
+ * \brief Checkup routine
+ * DEPRECATED: Use pkcs5_self_test() instead!
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int pbkdf2_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pbkdf2.h */
diff --git a/polarssl/pem.c b/polarssl/pem.c
new file mode 100644
index 0000000..e2e3998
--- /dev/null
+++ b/polarssl/pem.c
@@ -0,0 +1,355 @@
+/*
+ * Privacy Enhanced Mail (PEM) decoding
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_PEM_C)
+
+#include "polarssl/pem.h"
+#include "polarssl/base64.h"
+#include "polarssl/des.h"
+#include "polarssl/aes.h"
+#include "polarssl/md5.h"
+#include "polarssl/cipher.h"
+
+#include
+
+void pem_init( pem_context *ctx )
+{
+ memset( ctx, 0, sizeof( pem_context ) );
+}
+
+#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
+/*
+ * Read a 16-byte hex string and convert it to binary
+ */
+static int pem_get_iv( const unsigned char *s, unsigned char *iv, size_t iv_len )
+{
+ size_t i, j, k;
+
+ memset( iv, 0, iv_len );
+
+ for( i = 0; i < iv_len * 2; i++, s++ )
+ {
+ if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
+ if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
+ if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
+ return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+ k = ( ( i & 1 ) != 0 ) ? j : j << 4;
+
+ iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
+ }
+
+ return( 0 );
+}
+
+static void pem_pbkdf1( unsigned char *key, size_t keylen,
+ unsigned char *iv,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ md5_context md5_ctx;
+ unsigned char md5sum[16];
+ size_t use_len;
+
+ /*
+ * key[ 0..15] = MD5(pwd || IV)
+ */
+ md5_starts( &md5_ctx );
+ md5_update( &md5_ctx, pwd, pwdlen );
+ md5_update( &md5_ctx, iv, 8 );
+ md5_finish( &md5_ctx, md5sum );
+
+ if( keylen <= 16 )
+ {
+ memcpy( key, md5sum, keylen );
+
+ memset( &md5_ctx, 0, sizeof( md5_ctx ) );
+ memset( md5sum, 0, 16 );
+ return;
+ }
+
+ memcpy( key, md5sum, 16 );
+
+ /*
+ * key[16..23] = MD5(key[ 0..15] || pwd || IV])
+ */
+ md5_starts( &md5_ctx );
+ md5_update( &md5_ctx, md5sum, 16 );
+ md5_update( &md5_ctx, pwd, pwdlen );
+ md5_update( &md5_ctx, iv, 8 );
+ md5_finish( &md5_ctx, md5sum );
+
+ use_len = 16;
+ if( keylen < 32 )
+ use_len = keylen - 16;
+
+ memcpy( key + 16, md5sum, use_len );
+
+ memset( &md5_ctx, 0, sizeof( md5_ctx ) );
+ memset( md5sum, 0, 16 );
+}
+
+#if defined(POLARSSL_DES_C)
+/*
+ * Decrypt with DES-CBC, using PBKDF1 for key derivation
+ */
+static void pem_des_decrypt( unsigned char des_iv[8],
+ unsigned char *buf, size_t buflen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ des_context des_ctx;
+ unsigned char des_key[8];
+
+ pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen );
+
+ des_setkey_dec( &des_ctx, des_key );
+ des_crypt_cbc( &des_ctx, DES_DECRYPT, buflen,
+ des_iv, buf, buf );
+
+ memset( &des_ctx, 0, sizeof( des_ctx ) );
+ memset( des_key, 0, 8 );
+}
+
+/*
+ * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
+ */
+static void pem_des3_decrypt( unsigned char des3_iv[8],
+ unsigned char *buf, size_t buflen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ des3_context des3_ctx;
+ unsigned char des3_key[24];
+
+ pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen );
+
+ des3_set3key_dec( &des3_ctx, des3_key );
+ des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
+ des3_iv, buf, buf );
+
+ memset( &des3_ctx, 0, sizeof( des3_ctx ) );
+ memset( des3_key, 0, 24 );
+}
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_AES_C)
+/*
+ * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
+ */
+static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
+ unsigned char *buf, size_t buflen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ aes_context aes_ctx;
+ unsigned char aes_key[32];
+
+ pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen );
+
+ aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 );
+ aes_crypt_cbc( &aes_ctx, AES_DECRYPT, buflen,
+ aes_iv, buf, buf );
+
+ memset( &aes_ctx, 0, sizeof( aes_ctx ) );
+ memset( aes_key, 0, keylen );
+}
+#endif /* POLARSSL_AES_C */
+
+#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */
+
+int pem_read_buffer( pem_context *ctx, char *header, char *footer, const unsigned char *data, const unsigned char *pwd, size_t pwdlen, size_t *use_len )
+{
+ int ret, enc;
+ size_t len;
+ unsigned char *buf;
+ const unsigned char *s1, *s2, *end;
+#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
+ unsigned char pem_iv[16];
+ cipher_type_t enc_alg = POLARSSL_CIPHER_NONE;
+#else
+ ((void) pwd);
+ ((void) pwdlen);
+#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */
+
+ if( ctx == NULL )
+ return( POLARSSL_ERR_PEM_BAD_INPUT_DATA );
+
+ s1 = (unsigned char *) strstr( (const char *) data, header );
+
+ if( s1 == NULL )
+ return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+
+ s2 = (unsigned char *) strstr( (const char *) data, footer );
+
+ if( s2 == NULL || s2 <= s1 )
+ return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+
+ s1 += strlen( header );
+ if( *s1 == '\r' ) s1++;
+ if( *s1 == '\n' ) s1++;
+ else return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+
+ end = s2;
+ end += strlen( footer );
+ if( *end == '\r' ) end++;
+ if( *end == '\n' ) end++;
+ *use_len = end - data;
+
+ enc = 0;
+
+ if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
+ {
+#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
+ enc++;
+
+ s1 += 22;
+ if( *s1 == '\r' ) s1++;
+ if( *s1 == '\n' ) s1++;
+ else return( POLARSSL_ERR_PEM_INVALID_DATA );
+
+
+#if defined(POLARSSL_DES_C)
+ if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 )
+ {
+ enc_alg = POLARSSL_CIPHER_DES_EDE3_CBC;
+
+ s1 += 23;
+ if( pem_get_iv( s1, pem_iv, 8 ) != 0 )
+ return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+ s1 += 16;
+ }
+ else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 )
+ {
+ enc_alg = POLARSSL_CIPHER_DES_CBC;
+
+ s1 += 18;
+ if( pem_get_iv( s1, pem_iv, 8) != 0 )
+ return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+ s1 += 16;
+ }
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_AES_C)
+ if( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 )
+ {
+ if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 )
+ enc_alg = POLARSSL_CIPHER_AES_128_CBC;
+ else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 )
+ enc_alg = POLARSSL_CIPHER_AES_192_CBC;
+ else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 )
+ enc_alg = POLARSSL_CIPHER_AES_256_CBC;
+ else
+ return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG );
+
+ s1 += 22;
+ if( pem_get_iv( s1, pem_iv, 16 ) != 0 )
+ return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+ s1 += 32;
+ }
+#endif /* POLARSSL_AES_C */
+
+ if( enc_alg == POLARSSL_CIPHER_NONE )
+ return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG );
+
+ if( *s1 == '\r' ) s1++;
+ if( *s1 == '\n' ) s1++;
+ else return( POLARSSL_ERR_PEM_INVALID_DATA );
+#else
+ return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE );
+#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */
+ }
+
+ len = 0;
+ ret = base64_decode( NULL, &len, s1, s2 - s1 );
+
+ if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
+ return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
+
+ if( ( buf = (unsigned char *) malloc( len ) ) == NULL )
+ return( POLARSSL_ERR_PEM_MALLOC_FAILED );
+
+ if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
+ {
+ free( buf );
+ return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
+ }
+
+ if( enc != 0 )
+ {
+#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
+ if( pwd == NULL )
+ {
+ free( buf );
+ return( POLARSSL_ERR_PEM_PASSWORD_REQUIRED );
+ }
+
+#if defined(POLARSSL_DES_C)
+ if( enc_alg == POLARSSL_CIPHER_DES_EDE3_CBC )
+ pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
+ else if( enc_alg == POLARSSL_CIPHER_DES_CBC )
+ pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_AES_C)
+ if( enc_alg == POLARSSL_CIPHER_AES_128_CBC )
+ pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
+ else if( enc_alg == POLARSSL_CIPHER_AES_192_CBC )
+ pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
+ else if( enc_alg == POLARSSL_CIPHER_AES_256_CBC )
+ pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
+#endif /* POLARSSL_AES_C */
+
+ if( buf[0] != 0x30 || buf[1] != 0x82 ||
+ buf[4] != 0x02 || buf[5] != 0x01 )
+ {
+ free( buf );
+ return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH );
+ }
+#else
+ free( buf );
+ return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE );
+#endif
+ }
+
+ ctx->buf = buf;
+ ctx->buflen = len;
+
+ return( 0 );
+}
+
+void pem_free( pem_context *ctx )
+{
+ if( ctx->buf )
+ free( ctx->buf );
+
+ if( ctx->info )
+ free( ctx->info );
+
+ memset( ctx, 0, sizeof( pem_context ) );
+}
+
+#endif
diff --git a/polarssl/pem.h b/polarssl/pem.h
new file mode 100644
index 0000000..e95dc10
--- /dev/null
+++ b/polarssl/pem.h
@@ -0,0 +1,105 @@
+/**
+ * \file pem.h
+ *
+ * \brief Privacy Enhanced Mail (PEM) decoding
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PEM_H
+#define POLARSSL_PEM_H
+
+#include
+
+/**
+ * \name PEM Error codes
+ * These error codes are returned in case of errors reading the
+ * PEM data.
+ * \{
+ */
+#define POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /**< No PEM header or footer found. */
+#define POLARSSL_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */
+#define POLARSSL_ERR_PEM_MALLOC_FAILED -0x1180 /**< Failed to allocate memory. */
+#define POLARSSL_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */
+#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */
+#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */
+#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */
+#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */
+#define POLARSSL_ERR_PEM_BAD_INPUT_DATA -0x1480 /**< Bad input parameters to function. */
+/* \} name */
+
+/**
+ * \brief PEM context structure
+ */
+typedef struct
+{
+ unsigned char *buf; /*!< buffer for decoded data */
+ size_t buflen; /*!< length of the buffer */
+ unsigned char *info; /*!< buffer for extra header information */
+}
+pem_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief PEM context setup
+ *
+ * \param ctx context to be initialized
+ */
+void pem_init( pem_context *ctx );
+
+/**
+ * \brief Read a buffer for PEM information and store the resulting
+ * data into the specified context buffers.
+ *
+ * \param ctx context to use
+ * \param header header string to seek and expect
+ * \param footer footer string to seek and expect
+ * \param data source data to look in
+ * \param pwd password for decryption (can be NULL)
+ * \param pwdlen length of password
+ * \param use_len destination for total length used (set after header is
+ * correctly read, so unless you get
+ * POLARSSL_ERR_PEM_BAD_INPUT_DATA or
+ * POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is
+ * the length to skip)
+ *
+ * \return 0 on success, ior a specific PEM error code
+ */
+int pem_read_buffer( pem_context *ctx, char *header, char *footer,
+ const unsigned char *data,
+ const unsigned char *pwd,
+ size_t pwdlen, size_t *use_len );
+
+/**
+ * \brief PEM context memory freeing
+ *
+ * \param ctx context to be freed
+ */
+void pem_free( pem_context *ctx );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pem.h */
diff --git a/polarssl/pkcs11.c b/polarssl/pkcs11.c
new file mode 100644
index 0000000..b68d688
--- /dev/null
+++ b/polarssl/pkcs11.c
@@ -0,0 +1,238 @@
+/**
+ * \file pkcs11.c
+ *
+ * \brief Wrapper for PKCS#11 library libpkcs11-helper
+ *
+ * \author Adriaan de Jong
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/pkcs11.h"
+
+#if defined(POLARSSL_PKCS11_C)
+
+#include
+
+int pkcs11_x509_cert_init( x509_cert *cert, pkcs11h_certificate_t pkcs11_cert )
+{
+ int ret = 1;
+ unsigned char *cert_blob = NULL;
+ size_t cert_blob_size = 0;
+
+ if( cert == NULL )
+ {
+ ret = 2;
+ goto cleanup;
+ }
+
+ if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, &cert_blob_size ) != CKR_OK )
+ {
+ ret = 3;
+ goto cleanup;
+ }
+
+ cert_blob = malloc( cert_blob_size );
+ if( NULL == cert_blob )
+ {
+ ret = 4;
+ goto cleanup;
+ }
+
+ if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, &cert_blob_size ) != CKR_OK )
+ {
+ ret = 5;
+ goto cleanup;
+ }
+
+ if( 0 != x509parse_crt(cert, cert_blob, cert_blob_size ) )
+ {
+ ret = 6;
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ if( NULL != cert_blob )
+ free( cert_blob );
+
+ return ret;
+}
+
+
+int pkcs11_priv_key_init( pkcs11_context *priv_key,
+ pkcs11h_certificate_t pkcs11_cert )
+{
+ int ret = 1;
+ x509_cert cert;
+
+ memset( &cert, 0, sizeof( cert ) );
+
+ if( priv_key == NULL )
+ goto cleanup;
+
+ if( 0 != pkcs11_x509_cert_init( &cert, pkcs11_cert ) )
+ goto cleanup;
+
+ priv_key->len = cert.rsa.len;
+ priv_key->pkcs11h_cert = pkcs11_cert;
+
+ ret = 0;
+
+cleanup:
+ x509_free( &cert );
+
+ return ret;
+}
+
+void pkcs11_priv_key_free( pkcs11_context *priv_key )
+{
+ if( NULL != priv_key )
+ pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert );
+}
+
+int pkcs11_decrypt( pkcs11_context *ctx,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len )
+{
+ size_t input_len, output_len;
+
+ if( NULL == ctx )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ if( RSA_PUBLIC == mode )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ output_len = input_len = ctx->len;
+
+ if( input_len < 16 || input_len > output_max_len )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ /* Determine size of output buffer */
+ if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
+ input_len, NULL, &output_len ) != CKR_OK )
+ {
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ if( output_len > output_max_len )
+ return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
+
+ if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
+ input_len, output, &output_len ) != CKR_OK )
+ {
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+ *olen = output_len;
+ return( 0 );
+}
+
+int pkcs11_sign( pkcs11_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ size_t olen, asn_len;
+ unsigned char *p = sig;
+
+ if( NULL == ctx )
+ return POLARSSL_ERR_RSA_BAD_INPUT_DATA;
+
+ if( RSA_PUBLIC == mode )
+ return POLARSSL_ERR_RSA_BAD_INPUT_DATA;
+
+ olen = ctx->len;
+
+ switch( hash_id )
+ {
+ case SIG_RSA_RAW:
+ asn_len = 0;
+ memcpy( p, hash, hashlen );
+ break;
+
+ case SIG_RSA_MD2:
+ asn_len = OID_SIZE(ASN1_HASH_MDX);
+ memcpy( p, ASN1_HASH_MDX, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[13] = 2; break;
+
+ case SIG_RSA_MD4:
+ asn_len = OID_SIZE(ASN1_HASH_MDX);
+ memcpy( p, ASN1_HASH_MDX, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[13] = 4; break;
+
+ case SIG_RSA_MD5:
+ asn_len = OID_SIZE(ASN1_HASH_MDX);
+ memcpy( p, ASN1_HASH_MDX, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[13] = 5; break;
+
+ case SIG_RSA_SHA1:
+ asn_len = OID_SIZE(ASN1_HASH_SHA1);
+ memcpy( p, ASN1_HASH_SHA1, asn_len );
+ memcpy( p + 15, hash, hashlen );
+ break;
+
+ case SIG_RSA_SHA224:
+ asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+ memcpy( p, ASN1_HASH_SHA2X, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[1] += hashlen; p[14] = 4; p[18] += hashlen; break;
+
+ case SIG_RSA_SHA256:
+ asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+ memcpy( p, ASN1_HASH_SHA2X, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[1] += hashlen; p[14] = 1; p[18] += hashlen; break;
+
+ case SIG_RSA_SHA384:
+ asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+ memcpy( p, ASN1_HASH_SHA2X, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[1] += hashlen; p[14] = 2; p[18] += hashlen; break;
+
+ case SIG_RSA_SHA512:
+ asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+ memcpy( p, ASN1_HASH_SHA2X, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[1] += hashlen; p[14] = 3; p[18] += hashlen; break;
+
+ default:
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig,
+ asn_len + hashlen, sig, &olen ) != CKR_OK )
+ {
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ return( 0 );
+}
+
+#endif /* defined(POLARSSL_PKCS11_C) */
diff --git a/polarssl/pkcs11.h b/polarssl/pkcs11.h
new file mode 100644
index 0000000..3e95392
--- /dev/null
+++ b/polarssl/pkcs11.h
@@ -0,0 +1,161 @@
+/**
+ * \file pkcs11.h
+ *
+ * \brief Wrapper for PKCS#11 library libpkcs11-helper
+ *
+ * \author Adriaan de Jong
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PKCS11_H
+#define POLARSSL_PKCS11_H
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_PKCS11_C)
+
+#include "polarssl/x509.h"
+
+#include
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+/**
+ * Context for PKCS #11 private keys.
+ */
+typedef struct {
+ pkcs11h_certificate_t pkcs11h_cert;
+ int len;
+} pkcs11_context;
+
+/**
+ * Fill in a PolarSSL certificate, based on the given PKCS11 helper certificate.
+ *
+ * \param cert X.509 certificate to fill
+ * \param pkcs11h_cert PKCS #11 helper certificate
+ *
+ * \return 0 on success.
+ */
+int pkcs11_x509_cert_init( x509_cert *cert, pkcs11h_certificate_t pkcs11h_cert );
+
+/**
+ * Initialise a pkcs11_context, storing the given certificate. Note that the
+ * pkcs11_context will take over control of the certificate, freeing it when
+ * done.
+ *
+ * \param priv_key Private key structure to fill.
+ * \param pkcs11_cert PKCS #11 helper certificate
+ *
+ * \return 0 on success
+ */
+int pkcs11_priv_key_init( pkcs11_context *priv_key,
+ pkcs11h_certificate_t pkcs11_cert );
+
+/**
+ * Free the contents of the given private key context. Note that the structure
+ * itself is not freed.
+ *
+ * \param priv_key Private key structure to cleanup
+ */
+void pkcs11_priv_key_free( pkcs11_context *priv_key );
+
+/**
+ * \brief Do an RSA private key decrypt, then remove the message padding
+ *
+ * \param ctx PKCS #11 context
+ * \param mode must be RSA_PRIVATE, for compatibility with rsa.c's signature
+ * \param input buffer holding the encrypted data
+ * \param output buffer that will hold the plaintext
+ * \param olen will contain the plaintext length
+ * \param output_max_len maximum length of the output buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The output buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
+ * an error is thrown.
+ */
+int pkcs11_decrypt( pkcs11_context *ctx,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len );
+
+/**
+ * \brief Do a private RSA to sign a message digest
+ *
+ * \param ctx PKCS #11 context
+ * \param mode must be RSA_PRIVATE, for compatibility with rsa.c's signature
+ * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen message digest length (for SIG_RSA_RAW only)
+ * \param hash buffer holding the message digest
+ * \param sig buffer that will hold the ciphertext
+ *
+ * \return 0 if the signing operation was successful,
+ * or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The "sig" buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int pkcs11_sign( pkcs11_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * SSL/TLS wrappers for PKCS#11 functions
+ */
+static inline int ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen,
+ const unsigned char *input, unsigned char *output,
+ size_t output_max_len )
+{
+ return pkcs11_decrypt( (pkcs11_context *) ctx, mode, olen, input, output,
+ output_max_len );
+}
+
+static inline int ssl_pkcs11_sign( void *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ int mode, int hash_id, unsigned int hashlen,
+ const unsigned char *hash, unsigned char *sig )
+{
+ ((void) f_rng);
+ ((void) p_rng);
+ return pkcs11_sign( (pkcs11_context *) ctx, mode, hash_id,
+ hashlen, hash, sig );
+}
+
+static inline size_t ssl_pkcs11_key_len( void *ctx )
+{
+ return ( (pkcs11_context *) ctx )->len;
+}
+
+#endif /* POLARSSL_PKCS11_C */
+
+#endif /* POLARSSL_PKCS11_H */
diff --git a/polarssl/pkcs12.c b/polarssl/pkcs12.c
new file mode 100644
index 0000000..2ee9c5e
--- /dev/null
+++ b/polarssl/pkcs12.c
@@ -0,0 +1,330 @@
+/*
+ * PKCS#12 Personal Information Exchange Syntax
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The PKCS #12 Personal Information Exchange Syntax Standard v1.1
+ *
+ * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf
+ * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_PKCS12_C)
+
+#include "polarssl/pkcs12.h"
+#include "polarssl/asn1.h"
+#include "polarssl/cipher.h"
+
+#if defined(POLARSSL_ARC4_C)
+#include "polarssl/arc4.h"
+#endif
+
+#if defined(POLARSSL_DES_C)
+#include "polarssl/des.h"
+#endif
+
+static int pkcs12_parse_pbe_params( unsigned char **p,
+ const unsigned char *end,
+ asn1_buf *salt, int *iterations )
+{
+ int ret;
+ size_t len = 0;
+
+ /*
+ * pkcs-12PbeParams ::= SEQUENCE {
+ * salt OCTET STRING,
+ * iterations INTEGER
+ * }
+ *
+ */
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
+ }
+
+ end = *p + len;
+
+ if( ( ret = asn1_get_tag( p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 )
+ return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
+
+ salt->p = *p;
+ *p += salt->len;
+
+ if( ( ret = asn1_get_int( p, end, iterations ) ) != 0 )
+ return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
+
+ if( *p != end )
+ return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, md_type_t md_type,
+ const unsigned char *pwd, size_t pwdlen,
+ unsigned char *key, size_t keylen,
+ unsigned char *iv, size_t ivlen )
+{
+ int ret, iterations;
+ asn1_buf salt;
+ size_t i;
+ unsigned char *p, *end;
+ unsigned char unipwd[258];
+
+ memset(&salt, 0, sizeof(asn1_buf));
+ memset(&unipwd, 0, sizeof(unipwd));
+
+ p = pbe_params->p;
+ end = p + pbe_params->len;
+
+ if( ( ret = pkcs12_parse_pbe_params( &p, end, &salt, &iterations ) ) != 0 )
+ return( ret );
+
+ for(i = 0; i < pwdlen; i++)
+ unipwd[i * 2 + 1] = pwd[i];
+
+ if( ( ret = pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2,
+ salt.p, salt.len, md_type,
+ PKCS12_DERIVE_KEY, iterations ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( iv == NULL || ivlen == 0 )
+ return( 0 );
+
+ if( ( ret = pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2,
+ salt.p, salt.len, md_type,
+ PKCS12_DERIVE_IV, iterations ) ) != 0 )
+ {
+ return( ret );
+ }
+ return( 0 );
+}
+
+int pkcs12_pbe_sha1_rc4_128( asn1_buf *pbe_params, int mode,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *data, size_t len,
+ unsigned char *output )
+{
+#if !defined(POLARSSL_ARC4_C)
+ ((void) pbe_params);
+ ((void) mode);
+ ((void) pwd);
+ ((void) pwdlen);
+ ((void) data);
+ ((void) len);
+ ((void) output);
+ return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
+#else
+ int ret;
+ unsigned char key[16];
+ arc4_context ctx;
+ ((void) mode);
+
+ if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, POLARSSL_MD_SHA1,
+ pwd, pwdlen,
+ key, 16, NULL, 0 ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ arc4_setup( &ctx, key, 16 );
+ if( ( ret = arc4_crypt( &ctx, len, data, output ) ) != 0 )
+ return( ret );
+
+ return( 0 );
+#endif /* POLARSSL_ARC4_C */
+}
+
+int pkcs12_pbe( asn1_buf *pbe_params, int mode,
+ cipher_type_t cipher_type, md_type_t md_type,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *data, size_t len,
+ unsigned char *output )
+{
+ int ret, keylen = 0;
+ unsigned char key[32];
+ unsigned char iv[16];
+ const cipher_info_t *cipher_info;
+ cipher_context_t cipher_ctx;
+ size_t olen = 0;
+
+ cipher_info = cipher_info_from_type( cipher_type );
+ if( cipher_info == NULL )
+ return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
+
+ keylen = cipher_info->key_length / 8;
+
+ if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen,
+ key, keylen,
+ iv, cipher_info->iv_size ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 )
+ return( ret );
+
+ if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 )
+ return( ret );
+
+ if( ( ret = cipher_reset( &cipher_ctx, iv ) ) != 0 )
+ return( ret );
+
+ if( ( ret = cipher_update( &cipher_ctx, data, len,
+ output, &olen ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 )
+ return( POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH );
+
+ return( 0 );
+}
+
+static void pkcs12_fill_buffer( unsigned char *data, size_t data_len,
+ const unsigned char *filler, size_t fill_len )
+{
+ unsigned char *p = data;
+ size_t use_len;
+
+ while( data_len > 0 )
+ {
+ use_len = ( data_len > fill_len ) ? fill_len : data_len;
+ memcpy( p, filler, use_len );
+ p += use_len;
+ data_len -= use_len;
+ }
+}
+
+int pkcs12_derivation( unsigned char *data, size_t datalen,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *salt, size_t saltlen,
+ md_type_t md_type, int id, int iterations )
+{
+ int ret, i;
+ unsigned int j;
+
+ unsigned char diversifier[128];
+ unsigned char salt_block[128], pwd_block[128], hash_block[128];
+ unsigned char hash_output[POLARSSL_MD_MAX_SIZE];
+ unsigned char *p;
+ unsigned char c;
+
+ size_t hlen, use_len, v;
+
+ const md_info_t *md_info;
+ md_context_t md_ctx;
+
+ // This version only allows max of 64 bytes of password or salt
+ if( datalen > 128 || pwdlen > 64 || saltlen > 64 )
+ return( POLARSSL_ERR_PKCS12_BAD_INPUT_DATA );
+
+ md_info = md_info_from_type( md_type );
+ if( md_info == NULL )
+ return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
+
+ if ( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 )
+ return( ret );
+ hlen = md_get_size( md_info );
+
+ if( hlen <= 32 )
+ v = 64;
+ else
+ v = 128;
+
+ memset( diversifier, (unsigned char) id, v );
+
+ pkcs12_fill_buffer( salt_block, v, salt, saltlen );
+ pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen );
+
+ p = data;
+ while( datalen > 0 )
+ {
+ // Calculate hash( diversifier || salt_block || pwd_block )
+ if( ( ret = md_starts( &md_ctx ) ) != 0 )
+ return( ret );
+
+ if( ( ret = md_update( &md_ctx, diversifier, v ) ) != 0 )
+ return( ret );
+
+ if( ( ret = md_update( &md_ctx, salt_block, v ) ) != 0 )
+ return( ret );
+
+ if( ( ret = md_update( &md_ctx, pwd_block, v ) ) != 0 )
+ return( ret );
+
+ if( ( ret = md_finish( &md_ctx, hash_output ) ) != 0 )
+ return( ret );
+
+ // Perform remaining ( iterations - 1 ) recursive hash calculations
+ for( i = 1; i < iterations; i++ )
+ {
+ if( ( ret = md( md_info, hash_output, hlen, hash_output ) ) != 0 )
+ return( ret );
+ }
+
+ use_len = ( datalen > hlen ) ? hlen : datalen;
+ memcpy( p, hash_output, use_len );
+ datalen -= use_len;
+ p += use_len;
+
+ if( datalen == 0 )
+ break;
+
+ // Concatenating copies of hash_output into hash_block (B)
+ pkcs12_fill_buffer( hash_block, v, hash_output, hlen );
+
+ // B += 1
+ for( i = v; i > 0; i-- )
+ if( ++hash_block[i - 1] != 0 )
+ break;
+
+ // salt_block += B
+ c = 0;
+ for( i = v; i > 0; i-- )
+ {
+ j = salt_block[i - 1] + hash_block[i - 1] + c;
+ c = (unsigned char) (j >> 8);
+ salt_block[i - 1] = j & 0xFF;
+ }
+
+ // pwd_block += B
+ c = 0;
+ for( i = v; i > 0; i-- )
+ {
+ j = pwd_block[i - 1] + hash_block[i - 1] + c;
+ c = (unsigned char) (j >> 8);
+ pwd_block[i - 1] = j & 0xFF;
+ }
+ }
+
+ return( 0 );
+}
+
+#endif /* POLARSSL_PKCS12_C */
diff --git a/polarssl/pkcs12.h b/polarssl/pkcs12.h
new file mode 100644
index 0000000..ef559bd
--- /dev/null
+++ b/polarssl/pkcs12.h
@@ -0,0 +1,131 @@
+/**
+ * \file pkcs12.h
+ *
+ * \brief PKCS#12 Personal Information Exchange Syntax
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PKCS12_H
+#define POLARSSL_PKCS12_H
+
+#include
+
+#include "polarssl/md.h"
+#include "polarssl/cipher.h"
+#include "polarssl/asn1.h"
+
+#define POLARSSL_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 /**< Feature not available, e.g. unsupported encryption scheme. */
+#define POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 /**< PBE ASN.1 data not as expected. */
+#define POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 /**< Given private key password does not allow for correct decryption. */
+
+#define PKCS12_DERIVE_KEY 1 /*< encryption/decryption key */
+#define PKCS12_DERIVE_IV 2 /*< initialization vector */
+#define PKCS12_DERIVE_MAC_KEY 3 /*< integrity / MAC key */
+
+#define PKCS12_PBE_DECRYPT 0
+#define PKCS12_PBE_ENCRYPT 1
+
+/*
+ * PKCS#12 PBE types
+ */
+#define OID_PKCS12 "\x2a\x86\x48\x86\xf7\x0d\x01\x0c"
+#define OID_PKCS12_PBE_SHA1_RC4_128 OID_PKCS12 "\x01\x01"
+#define OID_PKCS12_PBE_SHA1_DES3_EDE_CBC OID_PKCS12 "\x01\x03"
+#define OID_PKCS12_PBE_SHA1_DES2_EDE_CBC OID_PKCS12 "\x01\x04"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief PKCS12 Password Based function (encryption / decryption)
+ * for pbeWithSHAAnd128BitRC4
+ *
+ * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure
+ * \param mode either PKCS12_PBE_ENCRYPT or PKCS12_PBE_DECRYPT
+ * \param pwd the password used (may be NULL if no password is used)
+ * \param pwdlen length of the password (may be 0)
+ * \param input the input data
+ * \param len data length
+ * \param output the output buffer
+ *
+ * \return 0 if successful, or a PolarSSL error code
+ */
+int pkcs12_pbe_sha1_rc4_128( asn1_buf *pbe_params, int mode,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *input, size_t len,
+ unsigned char *output );
+
+/**
+ * \brief PKCS12 Password Based function (encryption / decryption)
+ * for cipher-based and md-based PBE's
+ *
+ * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure
+ * \param mode either PKCS12_PBE_ENCRYPT or PKCS12_PBE_DECRYPT
+ * \param cipher_type the cipher used
+ * \param md_type the md used
+ * \param pwd the password used (may be NULL if no password is used)
+ * \param pwdlen length of the password (may be 0)
+ * \param input the input data
+ * \param len data length
+ * \param output the output buffer
+ *
+ * \return 0 if successful, or a PolarSSL error code
+ */
+int pkcs12_pbe( asn1_buf *pbe_params, int mode,
+ cipher_type_t cipher_type, md_type_t md_type,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *input, size_t len,
+ unsigned char *output );
+
+/**
+ * \brief The PKCS#12 derivation function uses a password and a salt
+ * to produce pseudo-random bits for a particular "purpose".
+ *
+ * Depending on the given id, this function can produce an
+ * encryption/decryption key, an nitialization vector or an
+ * integrity key.
+ *
+ * \param data buffer to store the derived data in
+ * \param datalen length to fill
+ * \param pwd password to use (may be NULL if no password is used)
+ * \param pwdlen length of the password (may be 0)
+ * \param salt salt buffer to use
+ * \param saltlen length of the salt
+ * \param md md type to use during the derivation
+ * \param id id that describes the purpose (can be PKCS12_DERIVE_KEY,
+ * PKCS12_DERIVE_IV or PKCS12_DERIVE_MAC_KEY)
+ * \param iterations number of iterations
+ *
+ * \return 0 if successful, or a MD, BIGNUM type error.
+ */
+int pkcs12_derivation( unsigned char *data, size_t datalen,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *salt, size_t saltlen,
+ md_type_t md, int id, int iterations );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pkcs12.h */
diff --git a/polarssl/pkcs5.c b/polarssl/pkcs5.c
new file mode 100644
index 0000000..8e55415
--- /dev/null
+++ b/polarssl/pkcs5.c
@@ -0,0 +1,415 @@
+/**
+ * \file pkcs5.c
+ *
+ * \brief PKCS#5 functions
+ *
+ * \author Mathias Olsson
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * PKCS#5 includes PBKDF2 and more
+ *
+ * http://tools.ietf.org/html/rfc2898 (Specification)
+ * http://tools.ietf.org/html/rfc6070 (Test vectors)
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_PKCS5_C)
+
+#include "polarssl/pkcs5.h"
+#include "polarssl/asn1.h"
+#include "polarssl/cipher.h"
+
+#define OID_CMP(oid_str, oid_buf) \
+ ( ( OID_SIZE(oid_str) == (oid_buf)->len ) && \
+ memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) == 0)
+
+static int pkcs5_parse_pbkdf2_params( unsigned char **p,
+ const unsigned char *end,
+ asn1_buf *salt, int *iterations,
+ int *keylen, md_type_t *md_type )
+{
+ int ret;
+ size_t len = 0;
+ asn1_buf prf_alg_oid;
+
+ /*
+ * PBKDF2-params ::= SEQUENCE {
+ * salt OCTET STRING,
+ * iterationCount INTEGER,
+ * keyLength INTEGER OPTIONAL
+ * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1
+ * }
+ *
+ */
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+ }
+
+ end = *p + len;
+
+ if( ( ret = asn1_get_tag( p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 )
+ return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+
+ salt->p = *p;
+ *p += salt->len;
+
+ if( ( ret = asn1_get_int( p, end, iterations ) ) != 0 )
+ return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+
+ if( *p == end )
+ return( 0 );
+
+ if( ( ret = asn1_get_int( p, end, keylen ) ) != 0 )
+ {
+ if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+ return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+ }
+
+ if( *p == end )
+ return( 0 );
+
+ if( ( ret = asn1_get_tag( p, end, &prf_alg_oid.len, ASN1_OID ) ) != 0 )
+ return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+
+ if( !OID_CMP( OID_HMAC_SHA1, &prf_alg_oid ) )
+ return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+ *md_type = POLARSSL_MD_SHA1;
+
+ if( *p != end )
+ return( POLARSSL_ERR_PKCS5_INVALID_FORMAT +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+int pkcs5_pbes2( asn1_buf *pbe_params, int mode,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *data, size_t datalen,
+ unsigned char *output )
+{
+ int ret, iterations = 0, keylen = 0;
+ unsigned char *p, *end, *end2;
+ asn1_buf kdf_alg_oid, enc_scheme_oid, salt;
+ md_type_t md_type = POLARSSL_MD_SHA1;
+ unsigned char key[32], iv[32];
+ size_t len = 0, olen = 0;
+ const md_info_t *md_info;
+ const cipher_info_t *cipher_info;
+ md_context_t md_ctx;
+ cipher_context_t cipher_ctx;
+
+ p = pbe_params->p;
+ end = p + pbe_params->len;
+
+ /*
+ * PBES2-params ::= SEQUENCE {
+ * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
+ * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
+ * }
+ */
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+ }
+
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+ }
+
+ end2 = p + len;
+
+ if( ( ret = asn1_get_tag( &p, end2, &kdf_alg_oid.len, ASN1_OID ) ) != 0 )
+ return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+
+ kdf_alg_oid.p = p;
+ p += kdf_alg_oid.len;
+
+ // Only PBKDF2 supported at the moment
+ //
+ if( !OID_CMP( OID_PKCS5_PBKDF2, &kdf_alg_oid ) )
+ return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+ if( ( ret = pkcs5_parse_pbkdf2_params( &p, end2,
+ &salt, &iterations, &keylen,
+ &md_type ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ md_info = md_info_from_type( md_type );
+ if( md_info == NULL )
+ return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+ }
+
+ end2 = p + len;
+
+ if( ( ret = asn1_get_tag( &p, end2, &enc_scheme_oid.len, ASN1_OID ) ) != 0 )
+ return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+
+ enc_scheme_oid.p = p;
+ p += enc_scheme_oid.len;
+
+#if defined(POLARSSL_DES_C)
+ // Only DES-CBC and DES-EDE3-CBC supported at the moment
+ //
+ if( OID_CMP( OID_DES_EDE3_CBC, &enc_scheme_oid ) )
+ {
+ cipher_info = cipher_info_from_type( POLARSSL_CIPHER_DES_EDE3_CBC );
+ }
+ else if( OID_CMP( OID_DES_CBC, &enc_scheme_oid ) )
+ {
+ cipher_info = cipher_info_from_type( POLARSSL_CIPHER_DES_CBC );
+ }
+ else
+#endif /* POLARSSL_DES_C */
+ return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+ if( cipher_info == NULL )
+ return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+ keylen = cipher_info->key_length / 8;
+
+ if( ( ret = asn1_get_tag( &p, end2, &len, ASN1_OCTET_STRING ) ) != 0 )
+ return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+
+ if( len != cipher_info->iv_size )
+ return( POLARSSL_ERR_PKCS5_INVALID_FORMAT );
+
+ memcpy( iv, p, len );
+
+ if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 )
+ return( ret );
+
+ if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 )
+ return( ret );
+
+ if ( ( ret = pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len,
+ iterations, keylen, key ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 )
+ return( ret );
+
+ if( ( ret = cipher_reset( &cipher_ctx, iv ) ) != 0 )
+ return( ret );
+
+ if( ( ret = cipher_update( &cipher_ctx, data, datalen,
+ output, &olen ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 )
+ return( POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH );
+
+ return( 0 );
+}
+
+int pkcs5_pbkdf2_hmac( md_context_t *ctx, const unsigned char *password,
+ size_t plen, const unsigned char *salt, size_t slen,
+ unsigned int iteration_count,
+ uint32_t key_length, unsigned char *output )
+{
+ int ret, j;
+ unsigned int i;
+ unsigned char md1[POLARSSL_MD_MAX_SIZE];
+ unsigned char work[POLARSSL_MD_MAX_SIZE];
+ unsigned char md_size = md_get_size( ctx->md_info );
+ size_t use_len;
+ unsigned char *out_p = output;
+ unsigned char counter[4];
+
+ memset( counter, 0, 4 );
+ counter[3] = 1;
+
+ if( iteration_count > 0xFFFFFFFF )
+ return( POLARSSL_ERR_PKCS5_BAD_INPUT_DATA );
+
+ while( key_length )
+ {
+ // U1 ends up in work
+ //
+ if( ( ret = md_hmac_starts( ctx, password, plen ) ) != 0 )
+ return( ret );
+
+ if( ( ret = md_hmac_update( ctx, salt, slen ) ) != 0 )
+ return( ret );
+
+ if( ( ret = md_hmac_update( ctx, counter, 4 ) ) != 0 )
+ return( ret );
+
+ if( ( ret = md_hmac_finish( ctx, work ) ) != 0 )
+ return( ret );
+
+ memcpy( md1, work, md_size );
+
+ for ( i = 1; i < iteration_count; i++ )
+ {
+ // U2 ends up in md1
+ //
+ if( ( ret = md_hmac_starts( ctx, password, plen ) ) != 0 )
+ return( ret );
+
+ if( ( ret = md_hmac_update( ctx, md1, md_size ) ) != 0 )
+ return( ret );
+
+ if( ( ret = md_hmac_finish( ctx, md1 ) ) != 0 )
+ return( ret );
+
+ // U1 xor U2
+ //
+ for( j = 0; j < md_size; j++ )
+ work[j] ^= md1[j];
+ }
+
+ use_len = ( key_length < md_size ) ? key_length : md_size;
+ memcpy( out_p, work, use_len );
+
+ key_length -= use_len;
+ out_p += use_len;
+
+ for( i = 4; i > 0; i-- )
+ if( ++counter[i - 1] != 0 )
+ break;
+ }
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include
+
+#define MAX_TESTS 6
+
+size_t plen[MAX_TESTS] =
+ { 8, 8, 8, 8, 24, 9 };
+
+unsigned char password[MAX_TESTS][32] =
+{
+ "password",
+ "password",
+ "password",
+ "password",
+ "passwordPASSWORDpassword",
+ "pass\0word",
+};
+
+size_t slen[MAX_TESTS] =
+ { 4, 4, 4, 4, 36, 5 };
+
+unsigned char salt[MAX_TESTS][40] =
+{
+ "salt",
+ "salt",
+ "salt",
+ "salt",
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt",
+ "sa\0lt",
+};
+
+uint32_t it_cnt[MAX_TESTS] =
+ { 1, 2, 4096, 16777216, 4096, 4096 };
+
+uint32_t key_len[MAX_TESTS] =
+ { 20, 20, 20, 20, 25, 16 };
+
+
+unsigned char result_key[MAX_TESTS][32] =
+{
+ { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
+ 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
+ 0x2f, 0xe0, 0x37, 0xa6 },
+ { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
+ 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
+ 0xd8, 0xde, 0x89, 0x57 },
+ { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
+ 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
+ 0x65, 0xa4, 0x29, 0xc1 },
+ { 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4,
+ 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c,
+ 0x26, 0x34, 0xe9, 0x84 },
+ { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
+ 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
+ 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
+ 0x38 },
+ { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
+ 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 },
+};
+
+int pkcs5_self_test( int verbose )
+{
+ md_context_t sha1_ctx;
+ const md_info_t *info_sha1;
+ int ret, i;
+ unsigned char key[64];
+
+ info_sha1 = md_info_from_type( POLARSSL_MD_SHA1 );
+ if( info_sha1 == NULL )
+ return( 1 );
+
+ if( ( ret = md_init_ctx( &sha1_ctx, info_sha1 ) ) != 0 )
+ return( 1 );
+
+ for( i = 0; i < MAX_TESTS; i++ )
+ {
+ printf( " PBKDF2 (SHA1) #%d: ", i );
+
+ ret = pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i],
+ slen[i], it_cnt[i], key_len[i], key );
+ if( ret != 0 ||
+ memcmp( result_key[i], key, key_len[i] ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_PKCS5_C */
diff --git a/polarssl/pkcs5.h b/polarssl/pkcs5.h
new file mode 100644
index 0000000..18f1a4b
--- /dev/null
+++ b/polarssl/pkcs5.h
@@ -0,0 +1,122 @@
+/**
+ * \file pkcs#5.h
+ *
+ * \brief PKCS#5 functions
+ *
+ * \author Mathias Olsson
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PKCS5_H
+#define POLARSSL_PKCS5_H
+
+#include
+
+#include "polarssl/asn1.h"
+#include "polarssl/md.h"
+
+#ifdef _MSC_VER
+#include
+typedef UINT32 uint32_t;
+#else
+#include
+#endif
+
+#define POLARSSL_ERR_PKCS5_BAD_INPUT_DATA -0x3f80 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_PKCS5_INVALID_FORMAT -0x3f00 /**< Unexpected ASN.1 data. */
+#define POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE -0x3e80 /**< Requested encryption or digest alg not available. */
+#define POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH -0x3e00 /**< Given private key password does not allow for correct decryption. */
+
+#define PKCS5_DECRYPT 0
+#define PKCS5_ENCRYPT 1
+
+/*
+ * PKCS#5 OIDs
+ */
+#define OID_PKCS5 "\x2a\x86\x48\x86\xf7\x0d\x01\x05"
+#define OID_PKCS5_PBES2 OID_PKCS5 "\x0d"
+#define OID_PKCS5_PBKDF2 OID_PKCS5 "\x0c"
+
+/*
+ * Encryption Algorithm OIDs
+ */
+#define OID_DES_CBC "\x2b\x0e\x03\x02\x07"
+#define OID_DES_EDE3_CBC "\x2a\x86\x48\x86\xf7\x0d\x03\x07"
+
+/*
+ * Digest Algorithm OIDs
+ */
+#define OID_HMAC_SHA1 "\x2a\x86\x48\x86\xf7\x0d\x02\x07"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief PKCS#5 PBES2 function
+ *
+ * \param pbe_params the ASN.1 algorithm parameters
+ * \param mode either PKCS5_DECRYPT or PKCS5_ENCRYPT
+ * \param pwd password to use when generating key
+ * \param plen length of password
+ * \param data data to process
+ * \param datalen length of data
+ * \param output output buffer
+ *
+ * \returns 0 on success, or a PolarSSL error code if verification fails.
+ */
+int pkcs5_pbes2( asn1_buf *pbe_params, int mode,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *data, size_t datalen,
+ unsigned char *output );
+
+/**
+ * \brief PKCS#5 PBKDF2 using HMAC
+ *
+ * \param ctx Generic HMAC context
+ * \param password Password to use when generating key
+ * \param plen Length of password
+ * \param salt Salt to use when generating key
+ * \param slen Length of salt
+ * \param iteration_count Iteration count
+ * \param key_length Length of generated key
+ * \param output Generated key. Must be at least as big as key_length
+ *
+ * \returns 0 on success, or a PolarSSL error code if verification fails.
+ */
+int pkcs5_pbkdf2_hmac( md_context_t *ctx, const unsigned char *password,
+ size_t plen, const unsigned char *salt, size_t slen,
+ unsigned int iteration_count,
+ uint32_t key_length, unsigned char *output );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int pkcs5_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pkcs5.h */
diff --git a/polarssl/rsa.c b/polarssl/rsa.c
new file mode 100644
index 0000000..e53d9a2
--- /dev/null
+++ b/polarssl/rsa.c
@@ -0,0 +1,1466 @@
+/*
+ * The RSA public-key cryptosystem
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
+ *
+ * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
+ * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_RSA_C)
+
+#include "polarssl/rsa.h"
+
+#if defined(POLARSSL_PKCS1_V21)
+#include "polarssl/md.h"
+#endif
+
+#include
+#include
+
+/*
+ * Initialize an RSA context
+ */
+void rsa_init( rsa_context *ctx,
+ int padding,
+ int hash_id )
+{
+ memset( ctx, 0, sizeof( rsa_context ) );
+
+ ctx->padding = padding;
+ ctx->hash_id = hash_id;
+}
+
+#if defined(POLARSSL_GENPRIME)
+
+/*
+ * Generate an RSA keypair
+ */
+int rsa_gen_key( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ unsigned int nbits, int exponent )
+{
+ int ret;
+ mpi P1, Q1, H, G;
+
+ if( f_rng == NULL || nbits < 128 || exponent < 3 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ mpi_init( &P1 ); mpi_init( &Q1 ); mpi_init( &H ); mpi_init( &G );
+
+ /*
+ * find primes P and Q with Q < P so that:
+ * GCD( E, (P-1)*(Q-1) ) == 1
+ */
+ MPI_CHK( mpi_lset( &ctx->E, exponent ) );
+
+ do
+ {
+ MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0,
+ f_rng, p_rng ) );
+
+ MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
+ f_rng, p_rng ) );
+
+ if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
+ mpi_swap( &ctx->P, &ctx->Q );
+
+ if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
+ continue;
+
+ MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
+ if( mpi_msb( &ctx->N ) != nbits )
+ continue;
+
+ MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
+ MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
+ MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
+ MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
+ }
+ while( mpi_cmp_int( &G, 1 ) != 0 );
+
+ /*
+ * D = E^-1 mod ((P-1)*(Q-1))
+ * DP = D mod (P - 1)
+ * DQ = D mod (Q - 1)
+ * QP = Q^-1 mod P
+ */
+ MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) );
+ MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
+ MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
+ MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
+
+ ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3;
+
+cleanup:
+
+ mpi_free( &P1 ); mpi_free( &Q1 ); mpi_free( &H ); mpi_free( &G );
+
+ if( ret != 0 )
+ {
+ rsa_free( ctx );
+ return( POLARSSL_ERR_RSA_KEY_GEN_FAILED + ret );
+ }
+
+ return( 0 );
+}
+
+#endif
+
+/*
+ * Check a public RSA key
+ */
+int rsa_check_pubkey( const rsa_context *ctx )
+{
+ if( !ctx->N.p || !ctx->E.p )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+ if( ( ctx->N.p[0] & 1 ) == 0 ||
+ ( ctx->E.p[0] & 1 ) == 0 )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+ if( mpi_msb( &ctx->N ) < 128 ||
+ mpi_msb( &ctx->N ) > POLARSSL_MPI_MAX_BITS )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+ if( mpi_msb( &ctx->E ) < 2 ||
+ mpi_msb( &ctx->E ) > 64 )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+ return( 0 );
+}
+
+/*
+ * Check a private RSA key
+ */
+int rsa_check_privkey( const rsa_context *ctx )
+{
+ int ret;
+ mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP;
+
+ if( ( ret = rsa_check_pubkey( ctx ) ) != 0 )
+ return( ret );
+
+ if( !ctx->P.p || !ctx->Q.p || !ctx->D.p )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+ mpi_init( &PQ ); mpi_init( &DE ); mpi_init( &P1 ); mpi_init( &Q1 );
+ mpi_init( &H ); mpi_init( &I ); mpi_init( &G ); mpi_init( &G2 );
+ mpi_init( &L1 ); mpi_init( &L2 ); mpi_init( &DP ); mpi_init( &DQ );
+ mpi_init( &QP );
+
+ MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
+ MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
+ MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
+ MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
+ MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
+ MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
+
+ MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) );
+ MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) );
+ MPI_CHK( mpi_mod_mpi( &I, &DE, &L1 ) );
+
+ MPI_CHK( mpi_mod_mpi( &DP, &ctx->D, &P1 ) );
+ MPI_CHK( mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) );
+ MPI_CHK( mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) );
+ /*
+ * Check for a valid PKCS1v2 private key
+ */
+ if( mpi_cmp_mpi( &PQ, &ctx->N ) != 0 ||
+ mpi_cmp_mpi( &DP, &ctx->DP ) != 0 ||
+ mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 ||
+ mpi_cmp_mpi( &QP, &ctx->QP ) != 0 ||
+ mpi_cmp_int( &L2, 0 ) != 0 ||
+ mpi_cmp_int( &I, 1 ) != 0 ||
+ mpi_cmp_int( &G, 1 ) != 0 )
+ {
+ ret = POLARSSL_ERR_RSA_KEY_CHECK_FAILED;
+ }
+
+cleanup:
+ mpi_free( &PQ ); mpi_free( &DE ); mpi_free( &P1 ); mpi_free( &Q1 );
+ mpi_free( &H ); mpi_free( &I ); mpi_free( &G ); mpi_free( &G2 );
+ mpi_free( &L1 ); mpi_free( &L2 ); mpi_free( &DP ); mpi_free( &DQ );
+ mpi_free( &QP );
+
+ if( ret == POLARSSL_ERR_RSA_KEY_CHECK_FAILED )
+ return( ret );
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED + ret );
+
+ return( 0 );
+}
+
+/*
+ * Do an RSA public key operation
+ */
+int rsa_public( rsa_context *ctx,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret;
+ size_t olen;
+ mpi T;
+
+ mpi_init( &T );
+
+ MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
+
+ if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+ {
+ mpi_free( &T );
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ olen = ctx->len;
+ MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
+ MPI_CHK( mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+
+ mpi_free( &T );
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_RSA_PUBLIC_FAILED + ret );
+
+ return( 0 );
+}
+
+/*
+ * Do an RSA private key operation
+ */
+int rsa_private( rsa_context *ctx,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret;
+ size_t olen;
+ mpi T, T1, T2;
+
+ mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 );
+
+ MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
+
+ if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+ {
+ mpi_free( &T );
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+#if defined(POLARSSL_RSA_NO_CRT)
+ MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
+#else
+ /*
+ * faster decryption using the CRT
+ *
+ * T1 = input ^ dP mod P
+ * T2 = input ^ dQ mod Q
+ */
+ MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
+ MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );
+
+ /*
+ * T = (T1 - T2) * (Q^-1 mod P) mod P
+ */
+ MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) );
+ MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) );
+ MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );
+
+ /*
+ * output = T2 + T * Q
+ */
+ MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
+ MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) );
+#endif
+
+ olen = ctx->len;
+ MPI_CHK( mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+
+ mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 );
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret );
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_PKCS1_V21)
+/**
+ * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer.
+ *
+ * \param dst buffer to mask
+ * \param dlen length of destination buffer
+ * \param src source of the mask generation
+ * \param slen length of the source buffer
+ * \param md_ctx message digest context to use
+ */
+static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, size_t slen,
+ md_context_t *md_ctx )
+{
+ unsigned char mask[POLARSSL_MD_MAX_SIZE];
+ unsigned char counter[4];
+ unsigned char *p;
+ unsigned int hlen;
+ size_t i, use_len;
+
+ memset( mask, 0, POLARSSL_MD_MAX_SIZE );
+ memset( counter, 0, 4 );
+
+ hlen = md_ctx->md_info->size;
+
+ // Generate and apply dbMask
+ //
+ p = dst;
+
+ while( dlen > 0 )
+ {
+ use_len = hlen;
+ if( dlen < hlen )
+ use_len = dlen;
+
+ md_starts( md_ctx );
+ md_update( md_ctx, src, slen );
+ md_update( md_ctx, counter, 4 );
+ md_finish( md_ctx, mask );
+
+ for( i = 0; i < use_len; ++i )
+ *p++ ^= mask[i];
+
+ counter[3]++;
+
+ dlen -= use_len;
+ }
+}
+#endif
+
+#if defined(POLARSSL_PKCS1_V21)
+/*
+ * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function
+ */
+int rsa_rsaes_oaep_encrypt( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ const unsigned char *label, size_t label_len,
+ size_t ilen,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ size_t olen;
+ int ret;
+ unsigned char *p = output;
+ unsigned int hlen;
+ const md_info_t *md_info;
+ md_context_t md_ctx;
+
+ if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ md_info = md_info_from_type( ctx->hash_id );
+
+ if( md_info == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ olen = ctx->len;
+ hlen = md_get_size( md_info );
+
+ if( olen < ilen + 2 * hlen + 2 || f_rng == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ memset( output, 0, olen );
+
+ *p++ = 0;
+
+ // Generate a random octet string seed
+ //
+ if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 )
+ return( POLARSSL_ERR_RSA_RNG_FAILED + ret );
+
+ p += hlen;
+
+ // Construct DB
+ //
+ md( md_info, label, label_len, p );
+ p += hlen;
+ p += olen - 2 * hlen - 2 - ilen;
+ *p++ = 1;
+ memcpy( p, input, ilen );
+
+ md_init_ctx( &md_ctx, md_info );
+
+ // maskedDB: Apply dbMask to DB
+ //
+ mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen,
+ &md_ctx );
+
+ // maskedSeed: Apply seedMask to seed
+ //
+ mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1,
+ &md_ctx );
+
+ md_free_ctx( &md_ctx );
+
+ return( ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, output, output )
+ : rsa_private( ctx, output, output ) );
+}
+#endif /* POLARSSL_PKCS1_V21 */
+
+/*
+ * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function
+ */
+int rsa_rsaes_pkcs1_v15_encrypt( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode, size_t ilen,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ size_t nb_pad, olen;
+ int ret;
+ unsigned char *p = output;
+
+ if( ctx->padding != RSA_PKCS_V15 || f_rng == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ olen = ctx->len;
+
+ if( olen < ilen + 11 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ nb_pad = olen - 3 - ilen;
+
+ *p++ = 0;
+ if( mode == RSA_PUBLIC )
+ {
+ *p++ = RSA_CRYPT;
+
+ while( nb_pad-- > 0 )
+ {
+ int rng_dl = 100;
+
+ do {
+ ret = f_rng( p_rng, p, 1 );
+ } while( *p == 0 && --rng_dl && ret == 0 );
+
+ // Check if RNG failed to generate data
+ //
+ if( rng_dl == 0 || ret != 0)
+ return POLARSSL_ERR_RSA_RNG_FAILED + ret;
+
+ p++;
+ }
+ }
+ else
+ {
+ *p++ = RSA_SIGN;
+
+ while( nb_pad-- > 0 )
+ *p++ = 0xFF;
+ }
+
+ *p++ = 0;
+ memcpy( p, input, ilen );
+
+ return( ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, output, output )
+ : rsa_private( ctx, output, output ) );
+}
+
+/*
+ * Add the message padding, then do an RSA operation
+ */
+int rsa_pkcs1_encrypt( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode, size_t ilen,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ switch( ctx->padding )
+ {
+ case RSA_PKCS_V15:
+ return rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen,
+ input, output );
+
+#if defined(POLARSSL_PKCS1_V21)
+ case RSA_PKCS_V21:
+ return rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0,
+ ilen, input, output );
+#endif
+
+ default:
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ }
+}
+
+#if defined(POLARSSL_PKCS1_V21)
+/*
+ * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function
+ */
+int rsa_rsaes_oaep_decrypt( rsa_context *ctx,
+ int mode,
+ const unsigned char *label, size_t label_len,
+ size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len )
+{
+ int ret;
+ size_t ilen;
+ unsigned char *p;
+ unsigned char buf[POLARSSL_MPI_MAX_SIZE];
+ unsigned char lhash[POLARSSL_MD_MAX_SIZE];
+ unsigned int hlen;
+ const md_info_t *md_info;
+ md_context_t md_ctx;
+
+ if( ctx->padding != RSA_PKCS_V21 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ ilen = ctx->len;
+
+ if( ilen < 16 || ilen > sizeof( buf ) )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ ret = ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, input, buf )
+ : rsa_private( ctx, input, buf );
+
+ if( ret != 0 )
+ return( ret );
+
+ p = buf;
+
+ if( *p++ != 0 )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ md_info = md_info_from_type( ctx->hash_id );
+ if( md_info == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ hlen = md_get_size( md_info );
+
+ md_init_ctx( &md_ctx, md_info );
+
+ // Generate lHash
+ //
+ md( md_info, label, label_len, lhash );
+
+ // seed: Apply seedMask to maskedSeed
+ //
+ mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
+ &md_ctx );
+
+ // DB: Apply dbMask to maskedDB
+ //
+ mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,
+ &md_ctx );
+
+ p += hlen;
+ md_free_ctx( &md_ctx );
+
+ // Check validity
+ //
+ if( memcmp( lhash, p, hlen ) != 0 )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ p += hlen;
+
+ while( *p == 0 && p < buf + ilen )
+ p++;
+
+ if( p == buf + ilen )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ if( *p++ != 0x01 )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ if (ilen - (p - buf) > output_max_len)
+ return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
+
+ *olen = ilen - (p - buf);
+ memcpy( output, p, *olen );
+
+ return( 0 );
+}
+#endif /* POLARSSL_PKCS1_V21 */
+
+/*
+ * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function
+ */
+int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len)
+{
+ int ret, correct = 1;
+ size_t ilen, pad_count = 0;
+ unsigned char *p, *q;
+ unsigned char bt;
+ unsigned char buf[POLARSSL_MPI_MAX_SIZE];
+
+ if( ctx->padding != RSA_PKCS_V15 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ ilen = ctx->len;
+
+ if( ilen < 16 || ilen > sizeof( buf ) )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ ret = ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, input, buf )
+ : rsa_private( ctx, input, buf );
+
+ if( ret != 0 )
+ return( ret );
+
+ p = buf;
+
+ if( *p++ != 0 )
+ correct = 0;
+
+ bt = *p++;
+ if( ( bt != RSA_CRYPT && mode == RSA_PRIVATE ) ||
+ ( bt != RSA_SIGN && mode == RSA_PUBLIC ) )
+ {
+ correct = 0;
+ }
+
+ if( bt == RSA_CRYPT )
+ {
+ while( *p != 0 && p < buf + ilen - 1 )
+ pad_count += ( *p++ != 0 );
+
+ correct &= ( *p == 0 && p < buf + ilen - 1 );
+
+ q = p;
+
+ // Also pass over all other bytes to reduce timing differences
+ //
+ while ( q < buf + ilen - 1 )
+ pad_count += ( *q++ != 0 );
+
+ // Prevent compiler optimization of pad_count
+ //
+ correct |= pad_count & 0x100000; /* Always 0 unless 1M bit keys */
+ p++;
+ }
+ else
+ {
+ while( *p == 0xFF && p < buf + ilen - 1 )
+ pad_count += ( *p++ == 0xFF );
+
+ correct &= ( *p == 0 && p < buf + ilen - 1 );
+
+ q = p;
+
+ // Also pass over all other bytes to reduce timing differences
+ //
+ while ( q < buf + ilen - 1 )
+ pad_count += ( *q++ != 0 );
+
+ // Prevent compiler optimization of pad_count
+ //
+ correct |= pad_count & 0x100000; /* Always 0 unless 1M bit keys */
+ p++;
+ }
+
+ if( correct == 0 )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ if (ilen - (p - buf) > output_max_len)
+ return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
+
+ *olen = ilen - (p - buf);
+ memcpy( output, p, *olen );
+
+ return( 0 );
+}
+
+/*
+ * Do an RSA operation, then remove the message padding
+ */
+int rsa_pkcs1_decrypt( rsa_context *ctx,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len)
+{
+ switch( ctx->padding )
+ {
+ case RSA_PKCS_V15:
+ return rsa_rsaes_pkcs1_v15_decrypt( ctx, mode, olen, input, output,
+ output_max_len );
+
+#if defined(POLARSSL_PKCS1_V21)
+ case RSA_PKCS_V21:
+ return rsa_rsaes_oaep_decrypt( ctx, mode, NULL, 0, olen, input,
+ output, output_max_len );
+#endif
+
+ default:
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ }
+}
+
+#if defined(POLARSSL_PKCS1_V21)
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function
+ */
+int rsa_rsassa_pss_sign( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ size_t olen;
+ unsigned char *p = sig;
+ unsigned char salt[POLARSSL_MD_MAX_SIZE];
+ unsigned int slen, hlen, offset = 0;
+ int ret;
+ size_t msb;
+ const md_info_t *md_info;
+ md_context_t md_ctx;
+
+ if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ olen = ctx->len;
+
+ switch( hash_id )
+ {
+ case SIG_RSA_MD2:
+ case SIG_RSA_MD4:
+ case SIG_RSA_MD5:
+ hashlen = 16;
+ break;
+
+ case SIG_RSA_SHA1:
+ hashlen = 20;
+ break;
+
+ case SIG_RSA_SHA224:
+ hashlen = 28;
+ break;
+
+ case SIG_RSA_SHA256:
+ hashlen = 32;
+ break;
+
+ case SIG_RSA_SHA384:
+ hashlen = 48;
+ break;
+
+ case SIG_RSA_SHA512:
+ hashlen = 64;
+ break;
+
+ default:
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ md_info = md_info_from_type( ctx->hash_id );
+ if( md_info == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ hlen = md_get_size( md_info );
+ slen = hlen;
+
+ if( olen < hlen + slen + 2 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ memset( sig, 0, olen );
+
+ msb = mpi_msb( &ctx->N ) - 1;
+
+ // Generate salt of length slen
+ //
+ if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
+ return( POLARSSL_ERR_RSA_RNG_FAILED + ret );
+
+ // Note: EMSA-PSS encoding is over the length of N - 1 bits
+ //
+ msb = mpi_msb( &ctx->N ) - 1;
+ p += olen - hlen * 2 - 2;
+ *p++ = 0x01;
+ memcpy( p, salt, slen );
+ p += slen;
+
+ md_init_ctx( &md_ctx, md_info );
+
+ // Generate H = Hash( M' )
+ //
+ md_starts( &md_ctx );
+ md_update( &md_ctx, p, 8 );
+ md_update( &md_ctx, hash, hashlen );
+ md_update( &md_ctx, salt, slen );
+ md_finish( &md_ctx, p );
+
+ // Compensate for boundary condition when applying mask
+ //
+ if( msb % 8 == 0 )
+ offset = 1;
+
+ // maskedDB: Apply dbMask to DB
+ //
+ mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx );
+
+ md_free_ctx( &md_ctx );
+
+ msb = mpi_msb( &ctx->N ) - 1;
+ sig[0] &= 0xFF >> ( olen * 8 - msb );
+
+ p += hlen;
+ *p++ = 0xBC;
+
+ return( ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, sig, sig )
+ : rsa_private( ctx, sig, sig ) );
+}
+#endif /* POLARSSL_PKCS1_V21 */
+
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function
+ */
+/*
+ * Do an RSA operation to sign the message digest
+ */
+int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ size_t nb_pad, olen;
+ unsigned char *p = sig;
+
+ if( ctx->padding != RSA_PKCS_V15 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ olen = ctx->len;
+
+ switch( hash_id )
+ {
+ case SIG_RSA_RAW:
+ nb_pad = olen - 3 - hashlen;
+ break;
+
+ case SIG_RSA_MD2:
+ case SIG_RSA_MD4:
+ case SIG_RSA_MD5:
+ nb_pad = olen - 3 - 34;
+ break;
+
+ case SIG_RSA_SHA1:
+ nb_pad = olen - 3 - 35;
+ break;
+
+ case SIG_RSA_SHA224:
+ nb_pad = olen - 3 - 47;
+ break;
+
+ case SIG_RSA_SHA256:
+ nb_pad = olen - 3 - 51;
+ break;
+
+ case SIG_RSA_SHA384:
+ nb_pad = olen - 3 - 67;
+ break;
+
+ case SIG_RSA_SHA512:
+ nb_pad = olen - 3 - 83;
+ break;
+
+
+ default:
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ if( ( nb_pad < 8 ) || ( nb_pad > olen ) )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ *p++ = 0;
+ *p++ = RSA_SIGN;
+ memset( p, 0xFF, nb_pad );
+ p += nb_pad;
+ *p++ = 0;
+
+ switch( hash_id )
+ {
+ case SIG_RSA_RAW:
+ memcpy( p, hash, hashlen );
+ break;
+
+ case SIG_RSA_MD2:
+ memcpy( p, ASN1_HASH_MDX, 18 );
+ memcpy( p + 18, hash, 16 );
+ p[13] = 2; break;
+
+ case SIG_RSA_MD4:
+ memcpy( p, ASN1_HASH_MDX, 18 );
+ memcpy( p + 18, hash, 16 );
+ p[13] = 4; break;
+
+ case SIG_RSA_MD5:
+ memcpy( p, ASN1_HASH_MDX, 18 );
+ memcpy( p + 18, hash, 16 );
+ p[13] = 5; break;
+
+ case SIG_RSA_SHA1:
+ memcpy( p, ASN1_HASH_SHA1, 15 );
+ memcpy( p + 15, hash, 20 );
+ break;
+
+ case SIG_RSA_SHA224:
+ memcpy( p, ASN1_HASH_SHA2X, 19 );
+ memcpy( p + 19, hash, 28 );
+ p[1] += 28; p[14] = 4; p[18] += 28; break;
+
+ case SIG_RSA_SHA256:
+ memcpy( p, ASN1_HASH_SHA2X, 19 );
+ memcpy( p + 19, hash, 32 );
+ p[1] += 32; p[14] = 1; p[18] += 32; break;
+
+ case SIG_RSA_SHA384:
+ memcpy( p, ASN1_HASH_SHA2X, 19 );
+ memcpy( p + 19, hash, 48 );
+ p[1] += 48; p[14] = 2; p[18] += 48; break;
+
+ case SIG_RSA_SHA512:
+ memcpy( p, ASN1_HASH_SHA2X, 19 );
+ memcpy( p + 19, hash, 64 );
+ p[1] += 64; p[14] = 3; p[18] += 64; break;
+
+ default:
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ return( ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, sig, sig )
+ : rsa_private( ctx, sig, sig ) );
+}
+
+/*
+ * Do an RSA operation to sign the message digest
+ */
+int rsa_pkcs1_sign( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ switch( ctx->padding )
+ {
+ case RSA_PKCS_V15:
+ return rsa_rsassa_pkcs1_v15_sign( ctx, mode, hash_id,
+ hashlen, hash, sig );
+
+#if defined(POLARSSL_PKCS1_V21)
+ case RSA_PKCS_V21:
+ return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, hash_id,
+ hashlen, hash, sig );
+#endif
+
+ default:
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ }
+}
+
+#if defined(POLARSSL_PKCS1_V21)
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function
+ */
+int rsa_rsassa_pss_verify( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ int ret;
+ size_t siglen;
+ unsigned char *p;
+ unsigned char buf[POLARSSL_MPI_MAX_SIZE];
+ unsigned char result[POLARSSL_MD_MAX_SIZE];
+ unsigned char zeros[8];
+ unsigned int hlen;
+ size_t slen, msb;
+ const md_info_t *md_info;
+ md_context_t md_ctx;
+
+ if( ctx->padding != RSA_PKCS_V21 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ siglen = ctx->len;
+
+ if( siglen < 16 || siglen > sizeof( buf ) )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ ret = ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, sig, buf )
+ : rsa_private( ctx, sig, buf );
+
+ if( ret != 0 )
+ return( ret );
+
+ p = buf;
+
+ if( buf[siglen - 1] != 0xBC )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ switch( hash_id )
+ {
+ case SIG_RSA_MD2:
+ case SIG_RSA_MD4:
+ case SIG_RSA_MD5:
+ hashlen = 16;
+ break;
+
+ case SIG_RSA_SHA1:
+ hashlen = 20;
+ break;
+
+ case SIG_RSA_SHA224:
+ hashlen = 28;
+ break;
+
+ case SIG_RSA_SHA256:
+ hashlen = 32;
+ break;
+
+ case SIG_RSA_SHA384:
+ hashlen = 48;
+ break;
+
+ case SIG_RSA_SHA512:
+ hashlen = 64;
+ break;
+
+ default:
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ md_info = md_info_from_type( ctx->hash_id );
+ if( md_info == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ hlen = md_get_size( md_info );
+ slen = siglen - hlen - 1;
+
+ memset( zeros, 0, 8 );
+
+ // Note: EMSA-PSS verification is over the length of N - 1 bits
+ //
+ msb = mpi_msb( &ctx->N ) - 1;
+
+ // Compensate for boundary condition when applying mask
+ //
+ if( msb % 8 == 0 )
+ {
+ p++;
+ siglen -= 1;
+ }
+ if( buf[0] >> ( 8 - siglen * 8 + msb ) )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ md_init_ctx( &md_ctx, md_info );
+
+ mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx );
+
+ buf[0] &= 0xFF >> ( siglen * 8 - msb );
+
+ while( *p == 0 && p < buf + siglen )
+ p++;
+
+ if( p == buf + siglen ||
+ *p++ != 0x01 )
+ {
+ md_free_ctx( &md_ctx );
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ }
+
+ slen -= p - buf;
+
+ // Generate H = Hash( M' )
+ //
+ md_starts( &md_ctx );
+ md_update( &md_ctx, zeros, 8 );
+ md_update( &md_ctx, hash, hashlen );
+ md_update( &md_ctx, p, slen );
+ md_finish( &md_ctx, result );
+
+ md_free_ctx( &md_ctx );
+
+ if( memcmp( p + slen, result, hlen ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+}
+#endif /* POLARSSL_PKCS1_V21 */
+
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function
+ */
+int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ int ret;
+ size_t len, siglen;
+ unsigned char *p, c;
+ unsigned char buf[POLARSSL_MPI_MAX_SIZE];
+
+ if( ctx->padding != RSA_PKCS_V15 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ siglen = ctx->len;
+
+ if( siglen < 16 || siglen > sizeof( buf ) )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ ret = ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, sig, buf )
+ : rsa_private( ctx, sig, buf );
+
+ if( ret != 0 )
+ return( ret );
+
+ p = buf;
+
+ if( *p++ != 0 || *p++ != RSA_SIGN )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ while( *p != 0 )
+ {
+ if( p >= buf + siglen - 1 || *p != 0xFF )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ p++;
+ }
+ p++;
+
+ len = siglen - ( p - buf );
+
+ if( len == 33 && hash_id == SIG_RSA_SHA1 )
+ {
+ if( memcmp( p, ASN1_HASH_SHA1_ALT, 13 ) == 0 &&
+ memcmp( p + 13, hash, 20 ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+ if( len == 34 )
+ {
+ c = p[13];
+ p[13] = 0;
+
+ if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+ if( ( c == 2 && hash_id == SIG_RSA_MD2 ) ||
+ ( c == 4 && hash_id == SIG_RSA_MD4 ) ||
+ ( c == 5 && hash_id == SIG_RSA_MD5 ) )
+ {
+ if( memcmp( p + 18, hash, 16 ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+ }
+
+ if( len == 35 && hash_id == SIG_RSA_SHA1 )
+ {
+ if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
+ memcmp( p + 15, hash, 20 ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+ if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) ||
+ ( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) ||
+ ( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) ||
+ ( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) )
+ {
+ c = p[1] - 17;
+ p[1] = 17;
+ p[14] = 0;
+
+ if( p[18] == c &&
+ memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 &&
+ memcmp( p + 19, hash, c ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+
+ if( len == hashlen && hash_id == SIG_RSA_RAW )
+ {
+ if( memcmp( p, hash, hashlen ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+}
+
+/*
+ * Do an RSA operation and check the message digest
+ */
+int rsa_pkcs1_verify( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ switch( ctx->padding )
+ {
+ case RSA_PKCS_V15:
+ return rsa_rsassa_pkcs1_v15_verify( ctx, mode, hash_id,
+ hashlen, hash, sig );
+
+#if defined(POLARSSL_PKCS1_V21)
+ case RSA_PKCS_V21:
+ return rsa_rsassa_pss_verify( ctx, mode, hash_id,
+ hashlen, hash, sig );
+#endif
+
+ default:
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ }
+}
+
+/*
+ * Free the components of an RSA key
+ */
+void rsa_free( rsa_context *ctx )
+{
+ mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN );
+ mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP );
+ mpi_free( &ctx->Q ); mpi_free( &ctx->P ); mpi_free( &ctx->D );
+ mpi_free( &ctx->E ); mpi_free( &ctx->N );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include "polarssl/sha1.h"
+
+/*
+ * Example RSA-1024 keypair, for test purposes
+ */
+#define KEY_LEN 128
+
+#define RSA_N "9292758453063D803DD603D5E777D788" \
+ "8ED1D5BF35786190FA2F23EBC0848AEA" \
+ "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
+ "7130B9CED7ACDF54CFC7555AC14EEBAB" \
+ "93A89813FBF3C4F8066D2D800F7C38A8" \
+ "1AE31942917403FF4946B0A83D3D3E05" \
+ "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
+ "5E94BB77B07507233A0BC7BAC8F90F79"
+
+#define RSA_E "10001"
+
+#define RSA_D "24BF6185468786FDD303083D25E64EFC" \
+ "66CA472BC44D253102F8B4A9D3BFA750" \
+ "91386C0077937FE33FA3252D28855837" \
+ "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
+ "DF79C5CE07EE72C7F123142198164234" \
+ "CABB724CF78B8173B9F880FC86322407" \
+ "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
+ "071513A1E85B5DFA031F21ECAE91A34D"
+
+#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
+ "2C01CAD19EA484A87EA4377637E75500" \
+ "FCB2005C5C7DD6EC4AC023CDA285D796" \
+ "C3D9E75E1EFC42488BB4F1D13AC30A57"
+
+#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
+ "E211C2B9E5DB1ED0BF61D0D9899620F4" \
+ "910E4168387E3C30AA1E00C339A79508" \
+ "8452DD96A9A5EA5D9DCA68DA636032AF"
+
+#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
+ "3C94D22288ACD763FD8E5600ED4A702D" \
+ "F84198A5F06C2E72236AE490C93F07F8" \
+ "3CC559CD27BC2D1CA488811730BB5725"
+
+#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
+ "D8AAEA56749EA28623272E4F7D0592AF" \
+ "7C1F1313CAC9471B5C523BFE592F517B" \
+ "407A1BD76C164B93DA2D32A383E58357"
+
+#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
+ "F38D18D2B2F0E2DD275AA977E2BF4411" \
+ "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
+ "A74206CEC169D74BF5A8C50D6F48EA08"
+
+#define PT_LEN 24
+#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
+ "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
+
+static int myrand( void *rng_state, unsigned char *output, size_t len )
+{
+ size_t i;
+
+ if( rng_state != NULL )
+ rng_state = NULL;
+
+ for( i = 0; i < len; ++i )
+ output[i] = rand();
+
+ return( 0 );
+}
+
+/*
+ * Checkup routine
+ */
+int rsa_self_test( int verbose )
+{
+ size_t len;
+ rsa_context rsa;
+ unsigned char rsa_plaintext[PT_LEN];
+ unsigned char rsa_decrypted[PT_LEN];
+ unsigned char rsa_ciphertext[KEY_LEN];
+#if defined(POLARSSL_SHA1_C)
+ unsigned char sha1sum[20];
+#endif
+
+ rsa_init( &rsa, RSA_PKCS_V15, 0 );
+
+ rsa.len = KEY_LEN;
+ mpi_read_string( &rsa.N , 16, RSA_N );
+ mpi_read_string( &rsa.E , 16, RSA_E );
+ mpi_read_string( &rsa.D , 16, RSA_D );
+ mpi_read_string( &rsa.P , 16, RSA_P );
+ mpi_read_string( &rsa.Q , 16, RSA_Q );
+ mpi_read_string( &rsa.DP, 16, RSA_DP );
+ mpi_read_string( &rsa.DQ, 16, RSA_DQ );
+ mpi_read_string( &rsa.QP, 16, RSA_QP );
+
+ if( verbose != 0 )
+ printf( " RSA key validation: " );
+
+ if( rsa_check_pubkey( &rsa ) != 0 ||
+ rsa_check_privkey( &rsa ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n PKCS#1 encryption : " );
+
+ memcpy( rsa_plaintext, RSA_PT, PT_LEN );
+
+ if( rsa_pkcs1_encrypt( &rsa, &myrand, NULL, RSA_PUBLIC, PT_LEN,
+ rsa_plaintext, rsa_ciphertext ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n PKCS#1 decryption : " );
+
+ if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len,
+ rsa_ciphertext, rsa_decrypted,
+ sizeof(rsa_decrypted) ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+#if defined(POLARSSL_SHA1_C)
+ if( verbose != 0 )
+ printf( "passed\n PKCS#1 data sign : " );
+
+ sha1( rsa_plaintext, PT_LEN, sha1sum );
+
+ if( rsa_pkcs1_sign( &rsa, NULL, NULL, RSA_PRIVATE, SIG_RSA_SHA1, 20,
+ sha1sum, rsa_ciphertext ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n PKCS#1 sig. verify: " );
+
+ if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20,
+ sha1sum, rsa_ciphertext ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n\n" );
+#endif /* POLARSSL_SHA1_C */
+
+ rsa_free( &rsa );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/rsa.h b/polarssl/rsa.h
new file mode 100644
index 0000000..2424cc1
--- /dev/null
+++ b/polarssl/rsa.h
@@ -0,0 +1,597 @@
+/**
+ * \file rsa.h
+ *
+ * \brief The RSA public-key cryptosystem
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_RSA_H
+#define POLARSSL_RSA_H
+
+#include "polarssl/bignum.h"
+
+/*
+ * RSA Error codes
+ */
+#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */
+#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */
+#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the libraries validity check. */
+#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */
+#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */
+#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */
+#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */
+#define POLARSSL_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */
+
+/*
+ * PKCS#1 constants
+ */
+#define SIG_RSA_RAW 0
+#define SIG_RSA_MD2 2
+#define SIG_RSA_MD4 3
+#define SIG_RSA_MD5 4
+#define SIG_RSA_SHA1 5
+#define SIG_RSA_SHA224 14
+#define SIG_RSA_SHA256 11
+#define SIG_RSA_SHA384 12
+#define SIG_RSA_SHA512 13
+
+#define RSA_PUBLIC 0
+#define RSA_PRIVATE 1
+
+#define RSA_PKCS_V15 0
+#define RSA_PKCS_V21 1
+
+#define RSA_SIGN 1
+#define RSA_CRYPT 2
+
+#define ASN1_STR_CONSTRUCTED_SEQUENCE "\x30"
+#define ASN1_STR_NULL "\x05"
+#define ASN1_STR_OID "\x06"
+#define ASN1_STR_OCTET_STRING "\x04"
+
+#define OID_DIGEST_ALG_MDX "\x2A\x86\x48\x86\xF7\x0D\x02\x00"
+#define OID_HASH_ALG_SHA1 "\x2b\x0e\x03\x02\x1a"
+#define OID_HASH_ALG_SHA2X "\x60\x86\x48\x01\x65\x03\x04\x02\x00"
+
+#define OID_ISO_MEMBER_BODIES "\x2a"
+#define OID_ISO_IDENTIFIED_ORG "\x2b"
+
+/*
+ * ISO Member bodies OID parts
+ */
+#define OID_COUNTRY_US "\x86\x48"
+#define OID_RSA_DATA_SECURITY "\x86\xf7\x0d"
+
+/*
+ * ISO Identified organization OID parts
+ */
+#define OID_OIW_SECSIG_SHA1 "\x0e\x03\x02\x1a"
+
+/*
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * digest Digest }
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * Digest ::= OCTET STRING
+ */
+#define ASN1_HASH_MDX \
+( \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x20" \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x0C" \
+ ASN1_STR_OID "\x08" \
+ OID_DIGEST_ALG_MDX \
+ ASN1_STR_NULL "\x00" \
+ ASN1_STR_OCTET_STRING "\x10" \
+)
+
+#define ASN1_HASH_SHA1 \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x21" \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x09" \
+ ASN1_STR_OID "\x05" \
+ OID_HASH_ALG_SHA1 \
+ ASN1_STR_NULL "\x00" \
+ ASN1_STR_OCTET_STRING "\x14"
+
+#define ASN1_HASH_SHA1_ALT \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x1F" \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x07" \
+ ASN1_STR_OID "\x05" \
+ OID_HASH_ALG_SHA1 \
+ ASN1_STR_OCTET_STRING "\x14"
+
+#define ASN1_HASH_SHA2X \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x11" \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x0d" \
+ ASN1_STR_OID "\x09" \
+ OID_HASH_ALG_SHA2X \
+ ASN1_STR_NULL "\x00" \
+ ASN1_STR_OCTET_STRING "\x00"
+
+/**
+ * \brief RSA context structure
+ */
+typedef struct
+{
+ int ver; /*!< always 0 */
+ size_t len; /*!< size(N) in chars */
+
+ mpi N; /*!< public modulus */
+ mpi E; /*!< public exponent */
+
+ mpi D; /*!< private exponent */
+ mpi P; /*!< 1st prime factor */
+ mpi Q; /*!< 2nd prime factor */
+ mpi DP; /*!< D % (P - 1) */
+ mpi DQ; /*!< D % (Q - 1) */
+ mpi QP; /*!< 1 / (Q % P) */
+
+ mpi RN; /*!< cached R^2 mod N */
+ mpi RP; /*!< cached R^2 mod P */
+ mpi RQ; /*!< cached R^2 mod Q */
+
+ int padding; /*!< RSA_PKCS_V15 for 1.5 padding and
+ RSA_PKCS_v21 for OAEP/PSS */
+ int hash_id; /*!< Hash identifier of md_type_t as
+ specified in the md.h header file
+ for the EME-OAEP and EMSA-PSS
+ encoding */
+}
+rsa_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Initialize an RSA context
+ *
+ * Note: Set padding to RSA_PKCS_V21 for the RSAES-OAEP
+ * encryption scheme and the RSASSA-PSS signature scheme.
+ *
+ * \param ctx RSA context to be initialized
+ * \param padding RSA_PKCS_V15 or RSA_PKCS_V21
+ * \param hash_id RSA_PKCS_V21 hash identifier
+ *
+ * \note The hash_id parameter is actually ignored
+ * when using RSA_PKCS_V15 padding.
+ */
+void rsa_init( rsa_context *ctx,
+ int padding,
+ int hash_id);
+
+/**
+ * \brief Generate an RSA keypair
+ *
+ * \param ctx RSA context that will hold the key
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ * \param nbits size of the public key in bits
+ * \param exponent public exponent (e.g., 65537)
+ *
+ * \note rsa_init() must be called beforehand to setup
+ * the RSA context.
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_gen_key( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ unsigned int nbits, int exponent );
+
+/**
+ * \brief Check a public RSA key
+ *
+ * \param ctx RSA context to be checked
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_check_pubkey( const rsa_context *ctx );
+
+/**
+ * \brief Check a private RSA key
+ *
+ * \param ctx RSA context to be checked
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_check_privkey( const rsa_context *ctx );
+
+/**
+ * \brief Do an RSA public key operation
+ *
+ * \param ctx RSA context
+ * \param input input buffer
+ * \param output output buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note This function does NOT take care of message
+ * padding. Also, be sure to set input[0] = 0 or assure that
+ * input is smaller than N.
+ *
+ * \note The input and output buffers must be large
+ * enough (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_public( rsa_context *ctx,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Do an RSA private key operation
+ *
+ * \param ctx RSA context
+ * \param input input buffer
+ * \param output output buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The input and output buffers must be large
+ * enough (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_private( rsa_context *ctx,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Generic wrapper to perform a PKCS#1 encryption using the
+ * mode from the context. Add the message padding, then do an
+ * RSA operation.
+ *
+ * \param ctx RSA context
+ * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding)
+ * \param p_rng RNG parameter
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param ilen contains the plaintext length
+ * \param input buffer holding the data to be encrypted
+ * \param output buffer that will hold the ciphertext
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The output buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_pkcs1_encrypt( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode, size_t ilen,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Perform a PKCS#1 v1.5 encryption (RSAES-PKCS1-v1_5-ENCRYPT)
+ *
+ * \param ctx RSA context
+ * \param f_rng RNG function (Needed for padding)
+ * \param p_rng RNG parameter
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param ilen contains the plaintext length
+ * \param input buffer holding the data to be encrypted
+ * \param output buffer that will hold the ciphertext
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The output buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_rsaes_pkcs1_v15_encrypt( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode, size_t ilen,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Perform a PKCS#1 v2.1 OAEP encryption (RSAES-OAEP-ENCRYPT)
+ *
+ * \param ctx RSA context
+ * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding)
+ * \param p_rng RNG parameter
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param label buffer holding the custom label to use
+ * \param label_len contains the label length
+ * \param ilen contains the plaintext length
+ * \param input buffer holding the data to be encrypted
+ * \param output buffer that will hold the ciphertext
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The output buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_rsaes_oaep_encrypt( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ const unsigned char *label, size_t label_len,
+ size_t ilen,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Generic wrapper to perform a PKCS#1 decryption using the
+ * mode from the context. Do an RSA operation, then remove
+ * the message padding
+ *
+ * \param ctx RSA context
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param olen will contain the plaintext length
+ * \param input buffer holding the encrypted data
+ * \param output buffer that will hold the plaintext
+ * \param output_max_len maximum length of the output buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The output buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
+ * an error is thrown.
+ */
+int rsa_pkcs1_decrypt( rsa_context *ctx,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len );
+
+/**
+ * \brief Perform a PKCS#1 v1.5 decryption (RSAES-PKCS1-v1_5-DECRYPT)
+ *
+ * \param ctx RSA context
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param olen will contain the plaintext length
+ * \param input buffer holding the encrypted data
+ * \param output buffer that will hold the plaintext
+ * \param output_max_len maximum length of the output buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The output buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
+ * an error is thrown.
+ */
+int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len );
+
+/**
+ * \brief Perform a PKCS#1 v2.1 OAEP decryption (RSAES-OAEP-DECRYPT)
+ *
+ * \param ctx RSA context
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param label buffer holding the custom label to use
+ * \param label_len contains the label length
+ * \param olen will contain the plaintext length
+ * \param input buffer holding the encrypted data
+ * \param output buffer that will hold the plaintext
+ * \param output_max_len maximum length of the output buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The output buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
+ * an error is thrown.
+ */
+int rsa_rsaes_oaep_decrypt( rsa_context *ctx,
+ int mode,
+ const unsigned char *label, size_t label_len,
+ size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len );
+
+/**
+ * \brief Generic wrapper to perform a PKCS#1 signature using the
+ * mode from the context. Do a private RSA operation to sign
+ * a message digest
+ *
+ * \param ctx RSA context
+ * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding)
+ * \param p_rng RNG parameter
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen message digest length (for SIG_RSA_RAW only)
+ * \param hash buffer holding the message digest
+ * \param sig buffer that will hold the ciphertext
+ *
+ * \return 0 if the signing operation was successful,
+ * or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The "sig" buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ *
+ * \note In case of PKCS#1 v2.1 encoding keep in mind that
+ * the hash_id in the RSA context is the one used for the
+ * encoding. hash_id in the function call is the type of hash
+ * that is encoded. According to RFC 3447 it is advised to
+ * keep both hashes the same.
+ */
+int rsa_pkcs1_sign( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * \brief Perform a PKCS#1 v1.5 signature (RSASSA-PKCS1-v1_5-SIGN)
+ *
+ * \param ctx RSA context
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen message digest length (for SIG_RSA_RAW only)
+ * \param hash buffer holding the message digest
+ * \param sig buffer that will hold the ciphertext
+ *
+ * \return 0 if the signing operation was successful,
+ * or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The "sig" buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * \brief Perform a PKCS#1 v2.1 PSS signature (RSASSA-PSS-SIGN)
+ *
+ * \param ctx RSA context
+ * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding)
+ * \param p_rng RNG parameter
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen message digest length (for SIG_RSA_RAW only)
+ * \param hash buffer holding the message digest
+ * \param sig buffer that will hold the ciphertext
+ *
+ * \return 0 if the signing operation was successful,
+ * or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The "sig" buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ *
+ * \note In case of PKCS#1 v2.1 encoding keep in mind that
+ * the hash_id in the RSA context is the one used for the
+ * encoding. hash_id in the function call is the type of hash
+ * that is encoded. According to RFC 3447 it is advised to
+ * keep both hashes the same.
+ */
+int rsa_rsassa_pss_sign( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * \brief Generic wrapper to perform a PKCS#1 verification using the
+ * mode from the context. Do a public RSA operation and check
+ * the message digest
+ *
+ * \param ctx points to an RSA public key
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen message digest length (for SIG_RSA_RAW only)
+ * \param hash buffer holding the message digest
+ * \param sig buffer holding the ciphertext
+ *
+ * \return 0 if the verify operation was successful,
+ * or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The "sig" buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ *
+ * \note In case of PKCS#1 v2.1 encoding keep in mind that
+ * the hash_id in the RSA context is the one used for the
+ * verification. hash_id in the function call is the type of hash
+ * that is verified. According to RFC 3447 it is advised to
+ * keep both hashes the same.
+ */
+int rsa_pkcs1_verify( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * \brief Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY)
+ *
+ * \param ctx points to an RSA public key
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen message digest length (for SIG_RSA_RAW only)
+ * \param hash buffer holding the message digest
+ * \param sig buffer holding the ciphertext
+ *
+ * \return 0 if the verify operation was successful,
+ * or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The "sig" buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY)
+ * \brief Do a public RSA and check the message digest
+ *
+ * \param ctx points to an RSA public key
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen message digest length (for SIG_RSA_RAW only)
+ * \param hash buffer holding the message digest
+ * \param sig buffer holding the ciphertext
+ *
+ * \return 0 if the verify operation was successful,
+ * or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The "sig" buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ *
+ * \note In case of PKCS#1 v2.1 encoding keep in mind that
+ * the hash_id in the RSA context is the one used for the
+ * verification. hash_id in the function call is the type of hash
+ * that is verified. According to RFC 3447 it is advised to
+ * keep both hashes the same.
+ */
+int rsa_rsassa_pss_verify( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * \brief Free the components of an RSA key
+ *
+ * \param ctx RSA Context to free
+ */
+void rsa_free( rsa_context *ctx );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int rsa_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* rsa.h */
diff --git a/polarssl/sha1.c b/polarssl/sha1.c
new file mode 100644
index 0000000..b301b09
--- /dev/null
+++ b/polarssl/sha1.c
@@ -0,0 +1,624 @@
+/*
+ * FIPS-180-1 compliant SHA-1 implementation
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The SHA-1 standard was published by NIST in 1993.
+ *
+ * http://www.itl.nist.gov/fipspubs/fip180-1.htm
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SHA1_C)
+
+#include "polarssl/sha1.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include
+#endif
+
+#if !defined(POLARSSL_SHA1_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+/*
+ * SHA-1 context setup
+ */
+void sha1_starts( sha1_context *ctx )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+ ctx->state[4] = 0xC3D2E1F0;
+}
+
+void sha1_process( sha1_context *ctx, const unsigned char data[64] )
+{
+ uint32_t temp, W[16], A, B, C, D, E;
+
+ GET_UINT32_BE( W[ 0], data, 0 );
+ GET_UINT32_BE( W[ 1], data, 4 );
+ GET_UINT32_BE( W[ 2], data, 8 );
+ GET_UINT32_BE( W[ 3], data, 12 );
+ GET_UINT32_BE( W[ 4], data, 16 );
+ GET_UINT32_BE( W[ 5], data, 20 );
+ GET_UINT32_BE( W[ 6], data, 24 );
+ GET_UINT32_BE( W[ 7], data, 28 );
+ GET_UINT32_BE( W[ 8], data, 32 );
+ GET_UINT32_BE( W[ 9], data, 36 );
+ GET_UINT32_BE( W[10], data, 40 );
+ GET_UINT32_BE( W[11], data, 44 );
+ GET_UINT32_BE( W[12], data, 48 );
+ GET_UINT32_BE( W[13], data, 52 );
+ GET_UINT32_BE( W[14], data, 56 );
+ GET_UINT32_BE( W[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define R(t) \
+( \
+ temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
+ W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
+ ( W[t & 0x0F] = S(temp,1) ) \
+)
+
+#define P(a,b,c,d,e,x) \
+{ \
+ e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+ P( A, B, C, D, E, W[0] );
+ P( E, A, B, C, D, W[1] );
+ P( D, E, A, B, C, W[2] );
+ P( C, D, E, A, B, W[3] );
+ P( B, C, D, E, A, W[4] );
+ P( A, B, C, D, E, W[5] );
+ P( E, A, B, C, D, W[6] );
+ P( D, E, A, B, C, W[7] );
+ P( C, D, E, A, B, W[8] );
+ P( B, C, D, E, A, W[9] );
+ P( A, B, C, D, E, W[10] );
+ P( E, A, B, C, D, W[11] );
+ P( D, E, A, B, C, W[12] );
+ P( C, D, E, A, B, W[13] );
+ P( B, C, D, E, A, W[14] );
+ P( A, B, C, D, E, W[15] );
+ P( E, A, B, C, D, R(16) );
+ P( D, E, A, B, C, R(17) );
+ P( C, D, E, A, B, R(18) );
+ P( B, C, D, E, A, R(19) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+ P( A, B, C, D, E, R(20) );
+ P( E, A, B, C, D, R(21) );
+ P( D, E, A, B, C, R(22) );
+ P( C, D, E, A, B, R(23) );
+ P( B, C, D, E, A, R(24) );
+ P( A, B, C, D, E, R(25) );
+ P( E, A, B, C, D, R(26) );
+ P( D, E, A, B, C, R(27) );
+ P( C, D, E, A, B, R(28) );
+ P( B, C, D, E, A, R(29) );
+ P( A, B, C, D, E, R(30) );
+ P( E, A, B, C, D, R(31) );
+ P( D, E, A, B, C, R(32) );
+ P( C, D, E, A, B, R(33) );
+ P( B, C, D, E, A, R(34) );
+ P( A, B, C, D, E, R(35) );
+ P( E, A, B, C, D, R(36) );
+ P( D, E, A, B, C, R(37) );
+ P( C, D, E, A, B, R(38) );
+ P( B, C, D, E, A, R(39) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+ P( A, B, C, D, E, R(40) );
+ P( E, A, B, C, D, R(41) );
+ P( D, E, A, B, C, R(42) );
+ P( C, D, E, A, B, R(43) );
+ P( B, C, D, E, A, R(44) );
+ P( A, B, C, D, E, R(45) );
+ P( E, A, B, C, D, R(46) );
+ P( D, E, A, B, C, R(47) );
+ P( C, D, E, A, B, R(48) );
+ P( B, C, D, E, A, R(49) );
+ P( A, B, C, D, E, R(50) );
+ P( E, A, B, C, D, R(51) );
+ P( D, E, A, B, C, R(52) );
+ P( C, D, E, A, B, R(53) );
+ P( B, C, D, E, A, R(54) );
+ P( A, B, C, D, E, R(55) );
+ P( E, A, B, C, D, R(56) );
+ P( D, E, A, B, C, R(57) );
+ P( C, D, E, A, B, R(58) );
+ P( B, C, D, E, A, R(59) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+ P( A, B, C, D, E, R(60) );
+ P( E, A, B, C, D, R(61) );
+ P( D, E, A, B, C, R(62) );
+ P( C, D, E, A, B, R(63) );
+ P( B, C, D, E, A, R(64) );
+ P( A, B, C, D, E, R(65) );
+ P( E, A, B, C, D, R(66) );
+ P( D, E, A, B, C, R(67) );
+ P( C, D, E, A, B, R(68) );
+ P( B, C, D, E, A, R(69) );
+ P( A, B, C, D, E, R(70) );
+ P( E, A, B, C, D, R(71) );
+ P( D, E, A, B, C, R(72) );
+ P( C, D, E, A, B, R(73) );
+ P( B, C, D, E, A, R(74) );
+ P( A, B, C, D, E, R(75) );
+ P( E, A, B, C, D, R(76) );
+ P( D, E, A, B, C, R(77) );
+ P( C, D, E, A, B, R(78) );
+ P( B, C, D, E, A, R(79) );
+
+#undef K
+#undef F
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+}
+
+/*
+ * SHA-1 process buffer
+ */
+void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
+{
+ size_t fill;
+ uint32_t left;
+
+ if( ilen <= 0 )
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (uint32_t) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, fill );
+ sha1_process( ctx, ctx->buffer );
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ sha1_process( ctx, input );
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ memcpy( (void *) (ctx->buffer + left), input, ilen );
+}
+
+static const unsigned char sha1_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-1 final digest
+ */
+void sha1_finish( sha1_context *ctx, unsigned char output[20] )
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT32_BE( high, msglen, 0 );
+ PUT_UINT32_BE( low, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ sha1_update( ctx, sha1_padding, padn );
+ sha1_update( ctx, msglen, 8 );
+
+ PUT_UINT32_BE( ctx->state[0], output, 0 );
+ PUT_UINT32_BE( ctx->state[1], output, 4 );
+ PUT_UINT32_BE( ctx->state[2], output, 8 );
+ PUT_UINT32_BE( ctx->state[3], output, 12 );
+ PUT_UINT32_BE( ctx->state[4], output, 16 );
+}
+
+#endif /* !POLARSSL_SHA1_ALT */
+
+/*
+ * output = SHA-1( input buffer )
+ */
+void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
+{
+ sha1_context ctx;
+
+ sha1_starts( &ctx );
+ sha1_update( &ctx, input, ilen );
+ sha1_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha1_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = SHA-1( file contents )
+ */
+int sha1_file( const char *path, unsigned char output[20] )
+{
+ FILE *f;
+ size_t n;
+ sha1_context ctx;
+ unsigned char buf[1024];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
+
+ sha1_starts( &ctx );
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ sha1_update( &ctx, buf, n );
+
+ sha1_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha1_context ) );
+
+ if( ferror( f ) != 0 )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * SHA-1 HMAC context setup
+ */
+void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen )
+{
+ size_t i;
+ unsigned char sum[20];
+
+ if( keylen > 64 )
+ {
+ sha1( key, keylen, sum );
+ keylen = 20;
+ key = sum;
+ }
+
+ memset( ctx->ipad, 0x36, 64 );
+ memset( ctx->opad, 0x5C, 64 );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+ ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+ }
+
+ sha1_starts( ctx );
+ sha1_update( ctx, ctx->ipad, 64 );
+
+ memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * SHA-1 HMAC process buffer
+ */
+void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
+{
+ sha1_update( ctx, input, ilen );
+}
+
+/*
+ * SHA-1 HMAC final digest
+ */
+void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
+{
+ unsigned char tmpbuf[20];
+
+ sha1_finish( ctx, tmpbuf );
+ sha1_starts( ctx );
+ sha1_update( ctx, ctx->opad, 64 );
+ sha1_update( ctx, tmpbuf, 20 );
+ sha1_finish( ctx, output );
+
+ memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * SHA1 HMAC context reset
+ */
+void sha1_hmac_reset( sha1_context *ctx )
+{
+ sha1_starts( ctx );
+ sha1_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-SHA-1( hmac key, input buffer )
+ */
+void sha1_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[20] )
+{
+ sha1_context ctx;
+
+ sha1_hmac_starts( &ctx, key, keylen );
+ sha1_hmac_update( &ctx, input, ilen );
+ sha1_hmac_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha1_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * FIPS-180-1 test vectors
+ */
+static unsigned char sha1_test_buf[3][57] =
+{
+ { "abc" },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+ { "" }
+};
+
+static const int sha1_test_buflen[3] =
+{
+ 3, 56, 1000
+};
+
+static const unsigned char sha1_test_sum[3][20] =
+{
+ { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
+ 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
+ { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
+ 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
+ { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
+ 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
+};
+
+/*
+ * RFC 2202 test vectors
+ */
+static unsigned char sha1_hmac_test_key[7][26] =
+{
+ { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+ "\x0B\x0B\x0B\x0B" },
+ { "Jefe" },
+ { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA" },
+ { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+ "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+ { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+ "\x0C\x0C\x0C\x0C" },
+ { "" }, /* 0xAA 80 times */
+ { "" }
+};
+
+static const int sha1_hmac_test_keylen[7] =
+{
+ 20, 4, 20, 25, 20, 80, 80
+};
+
+static unsigned char sha1_hmac_test_buf[7][74] =
+{
+ { "Hi There" },
+ { "what do ya want for nothing?" },
+ { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+ { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+ { "Test With Truncation" },
+ { "Test Using Larger Than Block-Size Key - Hash Key First" },
+ { "Test Using Larger Than Block-Size Key and Larger"
+ " Than One Block-Size Data" }
+};
+
+static const int sha1_hmac_test_buflen[7] =
+{
+ 8, 28, 50, 50, 20, 54, 73
+};
+
+static const unsigned char sha1_hmac_test_sum[7][20] =
+{
+ { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,
+ 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 },
+ { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,
+ 0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 },
+ { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,
+ 0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 },
+ { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,
+ 0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA },
+ { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,
+ 0x7B, 0xE1 },
+ { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,
+ 0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 },
+ { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,
+ 0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 }
+};
+
+/*
+ * Checkup routine
+ */
+int sha1_self_test( int verbose )
+{
+ int i, j, buflen;
+ unsigned char buf[1024];
+ unsigned char sha1sum[20];
+ sha1_context ctx;
+
+ /*
+ * SHA-1
+ */
+ for( i = 0; i < 3; i++ )
+ {
+ if( verbose != 0 )
+ printf( " SHA-1 test #%d: ", i + 1 );
+
+ sha1_starts( &ctx );
+
+ if( i == 2 )
+ {
+ memset( buf, 'a', buflen = 1000 );
+
+ for( j = 0; j < 1000; j++ )
+ sha1_update( &ctx, buf, buflen );
+ }
+ else
+ sha1_update( &ctx, sha1_test_buf[i],
+ sha1_test_buflen[i] );
+
+ sha1_finish( &ctx, sha1sum );
+
+ if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ for( i = 0; i < 7; i++ )
+ {
+ if( verbose != 0 )
+ printf( " HMAC-SHA-1 test #%d: ", i + 1 );
+
+ if( i == 5 || i == 6 )
+ {
+ memset( buf, '\xAA', buflen = 80 );
+ sha1_hmac_starts( &ctx, buf, buflen );
+ }
+ else
+ sha1_hmac_starts( &ctx, sha1_hmac_test_key[i],
+ sha1_hmac_test_keylen[i] );
+
+ sha1_hmac_update( &ctx, sha1_hmac_test_buf[i],
+ sha1_hmac_test_buflen[i] );
+
+ sha1_hmac_finish( &ctx, sha1sum );
+
+ buflen = ( i == 4 ) ? 12 : 20;
+
+ if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/sha1.h b/polarssl/sha1.h
new file mode 100644
index 0000000..ac7e5d3
--- /dev/null
+++ b/polarssl/sha1.h
@@ -0,0 +1,180 @@
+/**
+ * \file sha1.h
+ *
+ * \brief SHA-1 cryptographic hash function
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SHA1_H
+#define POLARSSL_SHA1_H
+
+#include "polarssl/config.h"
+
+#include
+
+#ifdef _MSC_VER
+#include
+typedef UINT32 uint32_t;
+#else
+#include
+#endif
+
+#define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */
+
+#if !defined(POLARSSL_SHA1_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief SHA-1 context structure
+ */
+typedef struct
+{
+ uint32_t total[2]; /*!< number of bytes processed */
+ uint32_t state[5]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+
+ unsigned char ipad[64]; /*!< HMAC: inner padding */
+ unsigned char opad[64]; /*!< HMAC: outer padding */
+}
+sha1_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief SHA-1 context setup
+ *
+ * \param ctx context to be initialized
+ */
+void sha1_starts( sha1_context *ctx );
+
+/**
+ * \brief SHA-1 process buffer
+ *
+ * \param ctx SHA-1 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief SHA-1 final digest
+ *
+ * \param ctx SHA-1 context
+ * \param output SHA-1 checksum result
+ */
+void sha1_finish( sha1_context *ctx, unsigned char output[20] );
+
+/* Internal use */
+void sha1_process( sha1_context *ctx, const unsigned char data[64] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* POLARSSL_SHA1_ALT */
+#include "polarssl/sha1_alt.h"
+#endif /* POLARSSL_SHA1_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Output = SHA-1( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output SHA-1 checksum result
+ */
+void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] );
+
+/**
+ * \brief Output = SHA-1( file contents )
+ *
+ * \param path input file name
+ * \param output SHA-1 checksum result
+ *
+ * \return 0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR
+ */
+int sha1_file( const char *path, unsigned char output[20] );
+
+/**
+ * \brief SHA-1 HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ */
+void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen );
+
+/**
+ * \brief SHA-1 HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief SHA-1 HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output SHA-1 HMAC checksum result
+ */
+void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );
+
+/**
+ * \brief SHA-1 HMAC context reset
+ *
+ * \param ctx HMAC context to be reset
+ */
+void sha1_hmac_reset( sha1_context *ctx );
+
+/**
+ * \brief Output = HMAC-SHA-1( hmac key, input buffer )
+ *
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output HMAC-SHA-1 result
+ */
+void sha1_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[20] );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int sha1_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha1.h */
diff --git a/polarssl/sha2.c b/polarssl/sha2.c
new file mode 100644
index 0000000..20772ec
--- /dev/null
+++ b/polarssl/sha2.c
@@ -0,0 +1,705 @@
+/*
+ * FIPS-180-2 compliant SHA-256 implementation
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The SHA-256 Secure Hash Standard was published by NIST in 2002.
+ *
+ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SHA2_C)
+
+#include "polarssl/sha2.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include
+#endif
+
+#if !defined(POLARSSL_SHA2_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+/*
+ * SHA-256 context setup
+ */
+void sha2_starts( sha2_context *ctx, int is224 )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ if( is224 == 0 )
+ {
+ /* SHA-256 */
+ ctx->state[0] = 0x6A09E667;
+ ctx->state[1] = 0xBB67AE85;
+ ctx->state[2] = 0x3C6EF372;
+ ctx->state[3] = 0xA54FF53A;
+ ctx->state[4] = 0x510E527F;
+ ctx->state[5] = 0x9B05688C;
+ ctx->state[6] = 0x1F83D9AB;
+ ctx->state[7] = 0x5BE0CD19;
+ }
+ else
+ {
+ /* SHA-224 */
+ ctx->state[0] = 0xC1059ED8;
+ ctx->state[1] = 0x367CD507;
+ ctx->state[2] = 0x3070DD17;
+ ctx->state[3] = 0xF70E5939;
+ ctx->state[4] = 0xFFC00B31;
+ ctx->state[5] = 0x68581511;
+ ctx->state[6] = 0x64F98FA7;
+ ctx->state[7] = 0xBEFA4FA4;
+ }
+
+ ctx->is224 = is224;
+}
+
+void sha2_process( sha2_context *ctx, const unsigned char data[64] )
+{
+ uint32_t temp1, temp2, W[64];
+ uint32_t A, B, C, D, E, F, G, H;
+
+ GET_UINT32_BE( W[ 0], data, 0 );
+ GET_UINT32_BE( W[ 1], data, 4 );
+ GET_UINT32_BE( W[ 2], data, 8 );
+ GET_UINT32_BE( W[ 3], data, 12 );
+ GET_UINT32_BE( W[ 4], data, 16 );
+ GET_UINT32_BE( W[ 5], data, 20 );
+ GET_UINT32_BE( W[ 6], data, 24 );
+ GET_UINT32_BE( W[ 7], data, 28 );
+ GET_UINT32_BE( W[ 8], data, 32 );
+ GET_UINT32_BE( W[ 9], data, 36 );
+ GET_UINT32_BE( W[10], data, 40 );
+ GET_UINT32_BE( W[11], data, 44 );
+ GET_UINT32_BE( W[12], data, 48 );
+ GET_UINT32_BE( W[13], data, 52 );
+ GET_UINT32_BE( W[14], data, 56 );
+ GET_UINT32_BE( W[15], data, 60 );
+
+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define R(t) \
+( \
+ W[t] = S1(W[t - 2]) + W[t - 7] + \
+ S0(W[t - 15]) + W[t - 16] \
+)
+
+#define P(a,b,c,d,e,f,g,h,x,K) \
+{ \
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
+ temp2 = S2(a) + F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+ F = ctx->state[5];
+ G = ctx->state[6];
+ H = ctx->state[7];
+
+ P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );
+ P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );
+ P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );
+ P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );
+ P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );
+ P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );
+ P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );
+ P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );
+ P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );
+ P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );
+ P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );
+ P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );
+ P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );
+ P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );
+ P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );
+ P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );
+ P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );
+ P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );
+ P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );
+ P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );
+ P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );
+ P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );
+ P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );
+ P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );
+ P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );
+ P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );
+ P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );
+ P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );
+ P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );
+ P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );
+ P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );
+ P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );
+ P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );
+ P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );
+ P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );
+ P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );
+ P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );
+ P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );
+ P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );
+ P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );
+ P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );
+ P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );
+ P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );
+ P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );
+ P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );
+ P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );
+ P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );
+ P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );
+ P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );
+ P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );
+ P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );
+ P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );
+ P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );
+ P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );
+ P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );
+ P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );
+ P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );
+ P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );
+ P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );
+ P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );
+ P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );
+ P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );
+ P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );
+ P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+ ctx->state[5] += F;
+ ctx->state[6] += G;
+ ctx->state[7] += H;
+}
+
+/*
+ * SHA-256 process buffer
+ */
+void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen )
+{
+ size_t fill;
+ uint32_t left;
+
+ if( ilen <= 0 )
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (uint32_t) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, fill );
+ sha2_process( ctx, ctx->buffer );
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ sha2_process( ctx, input );
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ memcpy( (void *) (ctx->buffer + left), input, ilen );
+}
+
+static const unsigned char sha2_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-256 final digest
+ */
+void sha2_finish( sha2_context *ctx, unsigned char output[32] )
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT32_BE( high, msglen, 0 );
+ PUT_UINT32_BE( low, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ sha2_update( ctx, sha2_padding, padn );
+ sha2_update( ctx, msglen, 8 );
+
+ PUT_UINT32_BE( ctx->state[0], output, 0 );
+ PUT_UINT32_BE( ctx->state[1], output, 4 );
+ PUT_UINT32_BE( ctx->state[2], output, 8 );
+ PUT_UINT32_BE( ctx->state[3], output, 12 );
+ PUT_UINT32_BE( ctx->state[4], output, 16 );
+ PUT_UINT32_BE( ctx->state[5], output, 20 );
+ PUT_UINT32_BE( ctx->state[6], output, 24 );
+
+ if( ctx->is224 == 0 )
+ PUT_UINT32_BE( ctx->state[7], output, 28 );
+}
+
+#endif /* !POLARSSL_SHA2_ALT */
+
+/*
+ * output = SHA-256( input buffer )
+ */
+void sha2( const unsigned char *input, size_t ilen,
+ unsigned char output[32], int is224 )
+{
+ sha2_context ctx;
+
+ sha2_starts( &ctx, is224 );
+ sha2_update( &ctx, input, ilen );
+ sha2_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha2_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = SHA-256( file contents )
+ */
+int sha2_file( const char *path, unsigned char output[32], int is224 )
+{
+ FILE *f;
+ size_t n;
+ sha2_context ctx;
+ unsigned char buf[1024];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_SHA2_FILE_IO_ERROR );
+
+ sha2_starts( &ctx, is224 );
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ sha2_update( &ctx, buf, n );
+
+ sha2_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha2_context ) );
+
+ if( ferror( f ) != 0 )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_SHA2_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * SHA-256 HMAC context setup
+ */
+void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen,
+ int is224 )
+{
+ size_t i;
+ unsigned char sum[32];
+
+ if( keylen > 64 )
+ {
+ sha2( key, keylen, sum, is224 );
+ keylen = ( is224 ) ? 28 : 32;
+ key = sum;
+ }
+
+ memset( ctx->ipad, 0x36, 64 );
+ memset( ctx->opad, 0x5C, 64 );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+ ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+ }
+
+ sha2_starts( ctx, is224 );
+ sha2_update( ctx, ctx->ipad, 64 );
+
+ memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * SHA-256 HMAC process buffer
+ */
+void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen )
+{
+ sha2_update( ctx, input, ilen );
+}
+
+/*
+ * SHA-256 HMAC final digest
+ */
+void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] )
+{
+ int is224, hlen;
+ unsigned char tmpbuf[32];
+
+ is224 = ctx->is224;
+ hlen = ( is224 == 0 ) ? 32 : 28;
+
+ sha2_finish( ctx, tmpbuf );
+ sha2_starts( ctx, is224 );
+ sha2_update( ctx, ctx->opad, 64 );
+ sha2_update( ctx, tmpbuf, hlen );
+ sha2_finish( ctx, output );
+
+ memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * SHA-256 HMAC context reset
+ */
+void sha2_hmac_reset( sha2_context *ctx )
+{
+ sha2_starts( ctx, ctx->is224 );
+ sha2_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-SHA-256( hmac key, input buffer )
+ */
+void sha2_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[32], int is224 )
+{
+ sha2_context ctx;
+
+ sha2_hmac_starts( &ctx, key, keylen, is224 );
+ sha2_hmac_update( &ctx, input, ilen );
+ sha2_hmac_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha2_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * FIPS-180-2 test vectors
+ */
+static unsigned char sha2_test_buf[3][57] =
+{
+ { "abc" },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+ { "" }
+};
+
+static const int sha2_test_buflen[3] =
+{
+ 3, 56, 1000
+};
+
+static const unsigned char sha2_test_sum[6][32] =
+{
+ /*
+ * SHA-224 test vectors
+ */
+ { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
+ 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
+ 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
+ 0xE3, 0x6C, 0x9D, 0xA7 },
+ { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
+ 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
+ 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
+ 0x52, 0x52, 0x25, 0x25 },
+ { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
+ 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
+ 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
+ 0x4E, 0xE7, 0xAD, 0x67 },
+
+ /*
+ * SHA-256 test vectors
+ */
+ { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
+ 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
+ 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
+ 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
+ { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
+ 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
+ 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
+ 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
+ { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
+ 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
+ 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
+ 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
+};
+
+/*
+ * RFC 4231 test vectors
+ */
+static unsigned char sha2_hmac_test_key[7][26] =
+{
+ { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+ "\x0B\x0B\x0B\x0B" },
+ { "Jefe" },
+ { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA" },
+ { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+ "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+ { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+ "\x0C\x0C\x0C\x0C" },
+ { "" }, /* 0xAA 131 times */
+ { "" }
+};
+
+static const int sha2_hmac_test_keylen[7] =
+{
+ 20, 4, 20, 25, 20, 131, 131
+};
+
+static unsigned char sha2_hmac_test_buf[7][153] =
+{
+ { "Hi There" },
+ { "what do ya want for nothing?" },
+ { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+ { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+ { "Test With Truncation" },
+ { "Test Using Larger Than Block-Size Key - Hash Key First" },
+ { "This is a test using a larger than block-size key "
+ "and a larger than block-size data. The key needs to "
+ "be hashed before being used by the HMAC algorithm." }
+};
+
+static const int sha2_hmac_test_buflen[7] =
+{
+ 8, 28, 50, 50, 20, 54, 152
+};
+
+static const unsigned char sha2_hmac_test_sum[14][32] =
+{
+ /*
+ * HMAC-SHA-224 test vectors
+ */
+ { 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19,
+ 0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F,
+ 0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F,
+ 0x53, 0x68, 0x4B, 0x22 },
+ { 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF,
+ 0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F,
+ 0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00,
+ 0x8F, 0xD0, 0x5E, 0x44 },
+ { 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6,
+ 0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64,
+ 0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1,
+ 0xEC, 0x83, 0x33, 0xEA },
+ { 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC,
+ 0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C,
+ 0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D,
+ 0xE7, 0xAF, 0xEC, 0x5A },
+ { 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37,
+ 0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 },
+ { 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD,
+ 0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2,
+ 0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27,
+ 0x3F, 0xA6, 0x87, 0x0E },
+ { 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02,
+ 0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD,
+ 0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9,
+ 0xF6, 0xF5, 0x65, 0xD1 },
+
+ /*
+ * HMAC-SHA-256 test vectors
+ */
+ { 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53,
+ 0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B,
+ 0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7,
+ 0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 },
+ { 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E,
+ 0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7,
+ 0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83,
+ 0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 },
+ { 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46,
+ 0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7,
+ 0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22,
+ 0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE },
+ { 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E,
+ 0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A,
+ 0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07,
+ 0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B },
+ { 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0,
+ 0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B },
+ { 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F,
+ 0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F,
+ 0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14,
+ 0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 },
+ { 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB,
+ 0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44,
+ 0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93,
+ 0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 }
+};
+
+/*
+ * Checkup routine
+ */
+int sha2_self_test( int verbose )
+{
+ int i, j, k, buflen;
+ unsigned char buf[1024];
+ unsigned char sha2sum[32];
+ sha2_context ctx;
+
+ for( i = 0; i < 6; i++ )
+ {
+ j = i % 3;
+ k = i < 3;
+
+ if( verbose != 0 )
+ printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 );
+
+ sha2_starts( &ctx, k );
+
+ if( j == 2 )
+ {
+ memset( buf, 'a', buflen = 1000 );
+
+ for( j = 0; j < 1000; j++ )
+ sha2_update( &ctx, buf, buflen );
+ }
+ else
+ sha2_update( &ctx, sha2_test_buf[j],
+ sha2_test_buflen[j] );
+
+ sha2_finish( &ctx, sha2sum );
+
+ if( memcmp( sha2sum, sha2_test_sum[i], 32 - k * 4 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ for( i = 0; i < 14; i++ )
+ {
+ j = i % 7;
+ k = i < 7;
+
+ if( verbose != 0 )
+ printf( " HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 );
+
+ if( j == 5 || j == 6 )
+ {
+ memset( buf, '\xAA', buflen = 131 );
+ sha2_hmac_starts( &ctx, buf, buflen, k );
+ }
+ else
+ sha2_hmac_starts( &ctx, sha2_hmac_test_key[j],
+ sha2_hmac_test_keylen[j], k );
+
+ sha2_hmac_update( &ctx, sha2_hmac_test_buf[j],
+ sha2_hmac_test_buflen[j] );
+
+ sha2_hmac_finish( &ctx, sha2sum );
+
+ buflen = ( j == 4 ) ? 16 : 32 - k * 4;
+
+ if( memcmp( sha2sum, sha2_hmac_test_sum[i], buflen ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/sha2.h b/polarssl/sha2.h
new file mode 100644
index 0000000..4f12472
--- /dev/null
+++ b/polarssl/sha2.h
@@ -0,0 +1,188 @@
+/**
+ * \file sha2.h
+ *
+ * \brief SHA-224 and SHA-256 cryptographic hash function
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SHA2_H
+#define POLARSSL_SHA2_H
+
+#include "polarssl/config.h"
+
+#include
+
+#ifdef _MSC_VER
+#include
+typedef UINT32 uint32_t;
+#else
+#include
+#endif
+
+#define POLARSSL_ERR_SHA2_FILE_IO_ERROR -0x0078 /**< Read/write error in file. */
+
+#if !defined(POLARSSL_SHA2_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief SHA-256 context structure
+ */
+typedef struct
+{
+ uint32_t total[2]; /*!< number of bytes processed */
+ uint32_t state[8]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+
+ unsigned char ipad[64]; /*!< HMAC: inner padding */
+ unsigned char opad[64]; /*!< HMAC: outer padding */
+ int is224; /*!< 0 => SHA-256, else SHA-224 */
+}
+sha2_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief SHA-256 context setup
+ *
+ * \param ctx context to be initialized
+ * \param is224 0 = use SHA256, 1 = use SHA224
+ */
+void sha2_starts( sha2_context *ctx, int is224 );
+
+/**
+ * \brief SHA-256 process buffer
+ *
+ * \param ctx SHA-256 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief SHA-256 final digest
+ *
+ * \param ctx SHA-256 context
+ * \param output SHA-224/256 checksum result
+ */
+void sha2_finish( sha2_context *ctx, unsigned char output[32] );
+
+/* Internal use */
+void sha2_process( sha2_context *ctx, const unsigned char data[64] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* POLARSSL_SHA2_ALT */
+#include "polarssl/sha2_alt.h"
+#endif /* POLARSSL_SHA2_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Output = SHA-256( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output SHA-224/256 checksum result
+ * \param is224 0 = use SHA256, 1 = use SHA224
+ */
+void sha2( const unsigned char *input, size_t ilen,
+ unsigned char output[32], int is224 );
+
+/**
+ * \brief Output = SHA-256( file contents )
+ *
+ * \param path input file name
+ * \param output SHA-224/256 checksum result
+ * \param is224 0 = use SHA256, 1 = use SHA224
+ *
+ * \return 0 if successful, or POLARSSL_ERR_SHA2_FILE_IO_ERROR
+ */
+int sha2_file( const char *path, unsigned char output[32], int is224 );
+
+/**
+ * \brief SHA-256 HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param is224 0 = use SHA256, 1 = use SHA224
+ */
+void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen,
+ int is224 );
+
+/**
+ * \brief SHA-256 HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief SHA-256 HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output SHA-224/256 HMAC checksum result
+ */
+void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] );
+
+/**
+ * \brief SHA-256 HMAC context reset
+ *
+ * \param ctx HMAC context to be reset
+ */
+void sha2_hmac_reset( sha2_context *ctx );
+
+/**
+ * \brief Output = HMAC-SHA-256( hmac key, input buffer )
+ *
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output HMAC-SHA-224/256 result
+ * \param is224 0 = use SHA256, 1 = use SHA224
+ */
+void sha2_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[32], int is224 );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int sha2_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha2.h */
diff --git a/polarssl/sha4.c b/polarssl/sha4.c
new file mode 100644
index 0000000..466420a
--- /dev/null
+++ b/polarssl/sha4.c
@@ -0,0 +1,760 @@
+/*
+ * FIPS-180-2 compliant SHA-384/512 implementation
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The SHA-512 Secure Hash Standard was published by NIST in 2002.
+ *
+ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SHA4_C)
+
+#include "polarssl/sha4.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include
+#endif
+
+#if !defined(POLARSSL_SHA4_ALT)
+
+/*
+ * 64-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT64_BE
+#define GET_UINT64_BE(n,b,i) \
+{ \
+ (n) = ( (uint64_t) (b)[(i) ] << 56 ) \
+ | ( (uint64_t) (b)[(i) + 1] << 48 ) \
+ | ( (uint64_t) (b)[(i) + 2] << 40 ) \
+ | ( (uint64_t) (b)[(i) + 3] << 32 ) \
+ | ( (uint64_t) (b)[(i) + 4] << 24 ) \
+ | ( (uint64_t) (b)[(i) + 5] << 16 ) \
+ | ( (uint64_t) (b)[(i) + 6] << 8 ) \
+ | ( (uint64_t) (b)[(i) + 7] ); \
+}
+#endif
+
+#ifndef PUT_UINT64_BE
+#define PUT_UINT64_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
+ (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 7] = (unsigned char) ( (n) ); \
+}
+#endif
+
+/*
+ * Round constants
+ */
+static const uint64_t K[80] =
+{
+ UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
+ UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
+ UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
+ UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
+ UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
+ UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
+ UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
+ UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
+ UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
+ UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
+ UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
+ UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
+ UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
+ UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
+ UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
+ UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
+ UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
+ UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
+ UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
+ UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
+ UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
+ UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
+ UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
+ UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
+ UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
+ UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
+ UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
+ UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
+ UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
+ UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
+ UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
+ UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
+ UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
+ UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
+ UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
+ UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
+ UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
+ UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
+ UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
+ UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
+};
+
+/*
+ * SHA-512 context setup
+ */
+void sha4_starts( sha4_context *ctx, int is384 )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ if( is384 == 0 )
+ {
+ /* SHA-512 */
+ ctx->state[0] = UL64(0x6A09E667F3BCC908);
+ ctx->state[1] = UL64(0xBB67AE8584CAA73B);
+ ctx->state[2] = UL64(0x3C6EF372FE94F82B);
+ ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
+ ctx->state[4] = UL64(0x510E527FADE682D1);
+ ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
+ ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
+ ctx->state[7] = UL64(0x5BE0CD19137E2179);
+ }
+ else
+ {
+ /* SHA-384 */
+ ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
+ ctx->state[1] = UL64(0x629A292A367CD507);
+ ctx->state[2] = UL64(0x9159015A3070DD17);
+ ctx->state[3] = UL64(0x152FECD8F70E5939);
+ ctx->state[4] = UL64(0x67332667FFC00B31);
+ ctx->state[5] = UL64(0x8EB44A8768581511);
+ ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
+ ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
+ }
+
+ ctx->is384 = is384;
+}
+
+static void sha4_process( sha4_context *ctx, const unsigned char data[128] )
+{
+ int i;
+ uint64_t temp1, temp2, W[80];
+ uint64_t A, B, C, D, E, F, G, H;
+
+#define SHR(x,n) (x >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
+
+#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
+#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
+
+#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
+#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define P(a,b,c,d,e,f,g,h,x,K) \
+{ \
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
+ temp2 = S2(a) + F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+}
+
+ for( i = 0; i < 16; i++ )
+ {
+ GET_UINT64_BE( W[i], data, i << 3 );
+ }
+
+ for( ; i < 80; i++ )
+ {
+ W[i] = S1(W[i - 2]) + W[i - 7] +
+ S0(W[i - 15]) + W[i - 16];
+ }
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+ F = ctx->state[5];
+ G = ctx->state[6];
+ H = ctx->state[7];
+ i = 0;
+
+ do
+ {
+ P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
+ P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
+ P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
+ P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
+ P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
+ P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
+ P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
+ P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
+ }
+ while( i < 80 );
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+ ctx->state[5] += F;
+ ctx->state[6] += G;
+ ctx->state[7] += H;
+}
+
+/*
+ * SHA-512 process buffer
+ */
+void sha4_update( sha4_context *ctx, const unsigned char *input, size_t ilen )
+{
+ size_t fill;
+ unsigned int left;
+
+ if( ilen <= 0 )
+ return;
+
+ left = (unsigned int) (ctx->total[0] & 0x7F);
+ fill = 128 - left;
+
+ ctx->total[0] += (uint64_t) ilen;
+
+ if( ctx->total[0] < (uint64_t) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, fill );
+ sha4_process( ctx, ctx->buffer );
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 128 )
+ {
+ sha4_process( ctx, input );
+ input += 128;
+ ilen -= 128;
+ }
+
+ if( ilen > 0 )
+ memcpy( (void *) (ctx->buffer + left), input, ilen );
+}
+
+static const unsigned char sha4_padding[128] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-512 final digest
+ */
+void sha4_finish( sha4_context *ctx, unsigned char output[64] )
+{
+ size_t last, padn;
+ uint64_t high, low;
+ unsigned char msglen[16];
+
+ high = ( ctx->total[0] >> 61 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT64_BE( high, msglen, 0 );
+ PUT_UINT64_BE( low, msglen, 8 );
+
+ last = (size_t)( ctx->total[0] & 0x7F );
+ padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
+
+ sha4_update( ctx, sha4_padding, padn );
+ sha4_update( ctx, msglen, 16 );
+
+ PUT_UINT64_BE( ctx->state[0], output, 0 );
+ PUT_UINT64_BE( ctx->state[1], output, 8 );
+ PUT_UINT64_BE( ctx->state[2], output, 16 );
+ PUT_UINT64_BE( ctx->state[3], output, 24 );
+ PUT_UINT64_BE( ctx->state[4], output, 32 );
+ PUT_UINT64_BE( ctx->state[5], output, 40 );
+
+ if( ctx->is384 == 0 )
+ {
+ PUT_UINT64_BE( ctx->state[6], output, 48 );
+ PUT_UINT64_BE( ctx->state[7], output, 56 );
+ }
+}
+
+#endif /* !POLARSSL_SHA4_ALT */
+
+/*
+ * output = SHA-512( input buffer )
+ */
+void sha4( const unsigned char *input, size_t ilen,
+ unsigned char output[64], int is384 )
+{
+ sha4_context ctx;
+
+ sha4_starts( &ctx, is384 );
+ sha4_update( &ctx, input, ilen );
+ sha4_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha4_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = SHA-512( file contents )
+ */
+int sha4_file( const char *path, unsigned char output[64], int is384 )
+{
+ FILE *f;
+ size_t n;
+ sha4_context ctx;
+ unsigned char buf[1024];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_SHA4_FILE_IO_ERROR );
+
+ sha4_starts( &ctx, is384 );
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ sha4_update( &ctx, buf, n );
+
+ sha4_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha4_context ) );
+
+ if( ferror( f ) != 0 )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_SHA4_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * SHA-512 HMAC context setup
+ */
+void sha4_hmac_starts( sha4_context *ctx, const unsigned char *key, size_t keylen,
+ int is384 )
+{
+ size_t i;
+ unsigned char sum[64];
+
+ if( keylen > 128 )
+ {
+ sha4( key, keylen, sum, is384 );
+ keylen = ( is384 ) ? 48 : 64;
+ key = sum;
+ }
+
+ memset( ctx->ipad, 0x36, 128 );
+ memset( ctx->opad, 0x5C, 128 );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+ ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+ }
+
+ sha4_starts( ctx, is384 );
+ sha4_update( ctx, ctx->ipad, 128 );
+
+ memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * SHA-512 HMAC process buffer
+ */
+void sha4_hmac_update( sha4_context *ctx,
+ const unsigned char *input, size_t ilen )
+{
+ sha4_update( ctx, input, ilen );
+}
+
+/*
+ * SHA-512 HMAC final digest
+ */
+void sha4_hmac_finish( sha4_context *ctx, unsigned char output[64] )
+{
+ int is384, hlen;
+ unsigned char tmpbuf[64];
+
+ is384 = ctx->is384;
+ hlen = ( is384 == 0 ) ? 64 : 48;
+
+ sha4_finish( ctx, tmpbuf );
+ sha4_starts( ctx, is384 );
+ sha4_update( ctx, ctx->opad, 128 );
+ sha4_update( ctx, tmpbuf, hlen );
+ sha4_finish( ctx, output );
+
+ memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * SHA-512 HMAC context reset
+ */
+void sha4_hmac_reset( sha4_context *ctx )
+{
+ sha4_starts( ctx, ctx->is384 );
+ sha4_update( ctx, ctx->ipad, 128 );
+}
+
+/*
+ * output = HMAC-SHA-512( hmac key, input buffer )
+ */
+void sha4_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[64], int is384 )
+{
+ sha4_context ctx;
+
+ sha4_hmac_starts( &ctx, key, keylen, is384 );
+ sha4_hmac_update( &ctx, input, ilen );
+ sha4_hmac_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha4_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * FIPS-180-2 test vectors
+ */
+static unsigned char sha4_test_buf[3][113] =
+{
+ { "abc" },
+ { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
+ { "" }
+};
+
+static const int sha4_test_buflen[3] =
+{
+ 3, 112, 1000
+};
+
+static const unsigned char sha4_test_sum[6][64] =
+{
+ /*
+ * SHA-384 test vectors
+ */
+ { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
+ 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
+ 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
+ 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
+ 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
+ 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },
+ { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
+ 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
+ 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
+ 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
+ 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
+ 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },
+ { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,
+ 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,
+ 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
+ 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
+ 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
+ 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
+
+ /*
+ * SHA-512 test vectors
+ */
+ { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
+ 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
+ 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
+ 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
+ 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
+ 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
+ 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
+ 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },
+ { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
+ 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
+ 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
+ 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
+ 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
+ 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
+ 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
+ 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },
+ { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
+ 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
+ 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
+ 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
+ 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
+ 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
+ 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
+ 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
+};
+
+/*
+ * RFC 4231 test vectors
+ */
+static unsigned char sha4_hmac_test_key[7][26] =
+{
+ { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+ "\x0B\x0B\x0B\x0B" },
+ { "Jefe" },
+ { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA" },
+ { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+ "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+ { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+ "\x0C\x0C\x0C\x0C" },
+ { "" }, /* 0xAA 131 times */
+ { "" }
+};
+
+static const int sha4_hmac_test_keylen[7] =
+{
+ 20, 4, 20, 25, 20, 131, 131
+};
+
+static unsigned char sha4_hmac_test_buf[7][153] =
+{
+ { "Hi There" },
+ { "what do ya want for nothing?" },
+ { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+ { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+ { "Test With Truncation" },
+ { "Test Using Larger Than Block-Size Key - Hash Key First" },
+ { "This is a test using a larger than block-size key "
+ "and a larger than block-size data. The key needs to "
+ "be hashed before being used by the HMAC algorithm." }
+};
+
+static const int sha4_hmac_test_buflen[7] =
+{
+ 8, 28, 50, 50, 20, 54, 152
+};
+
+static const unsigned char sha4_hmac_test_sum[14][64] =
+{
+ /*
+ * HMAC-SHA-384 test vectors
+ */
+ { 0xAF, 0xD0, 0x39, 0x44, 0xD8, 0x48, 0x95, 0x62,
+ 0x6B, 0x08, 0x25, 0xF4, 0xAB, 0x46, 0x90, 0x7F,
+ 0x15, 0xF9, 0xDA, 0xDB, 0xE4, 0x10, 0x1E, 0xC6,
+ 0x82, 0xAA, 0x03, 0x4C, 0x7C, 0xEB, 0xC5, 0x9C,
+ 0xFA, 0xEA, 0x9E, 0xA9, 0x07, 0x6E, 0xDE, 0x7F,
+ 0x4A, 0xF1, 0x52, 0xE8, 0xB2, 0xFA, 0x9C, 0xB6 },
+ { 0xAF, 0x45, 0xD2, 0xE3, 0x76, 0x48, 0x40, 0x31,
+ 0x61, 0x7F, 0x78, 0xD2, 0xB5, 0x8A, 0x6B, 0x1B,
+ 0x9C, 0x7E, 0xF4, 0x64, 0xF5, 0xA0, 0x1B, 0x47,
+ 0xE4, 0x2E, 0xC3, 0x73, 0x63, 0x22, 0x44, 0x5E,
+ 0x8E, 0x22, 0x40, 0xCA, 0x5E, 0x69, 0xE2, 0xC7,
+ 0x8B, 0x32, 0x39, 0xEC, 0xFA, 0xB2, 0x16, 0x49 },
+ { 0x88, 0x06, 0x26, 0x08, 0xD3, 0xE6, 0xAD, 0x8A,
+ 0x0A, 0xA2, 0xAC, 0xE0, 0x14, 0xC8, 0xA8, 0x6F,
+ 0x0A, 0xA6, 0x35, 0xD9, 0x47, 0xAC, 0x9F, 0xEB,
+ 0xE8, 0x3E, 0xF4, 0xE5, 0x59, 0x66, 0x14, 0x4B,
+ 0x2A, 0x5A, 0xB3, 0x9D, 0xC1, 0x38, 0x14, 0xB9,
+ 0x4E, 0x3A, 0xB6, 0xE1, 0x01, 0xA3, 0x4F, 0x27 },
+ { 0x3E, 0x8A, 0x69, 0xB7, 0x78, 0x3C, 0x25, 0x85,
+ 0x19, 0x33, 0xAB, 0x62, 0x90, 0xAF, 0x6C, 0xA7,
+ 0x7A, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9C,
+ 0xC5, 0x57, 0x7C, 0x6E, 0x1F, 0x57, 0x3B, 0x4E,
+ 0x68, 0x01, 0xDD, 0x23, 0xC4, 0xA7, 0xD6, 0x79,
+ 0xCC, 0xF8, 0xA3, 0x86, 0xC6, 0x74, 0xCF, 0xFB },
+ { 0x3A, 0xBF, 0x34, 0xC3, 0x50, 0x3B, 0x2A, 0x23,
+ 0xA4, 0x6E, 0xFC, 0x61, 0x9B, 0xAE, 0xF8, 0x97 },
+ { 0x4E, 0xCE, 0x08, 0x44, 0x85, 0x81, 0x3E, 0x90,
+ 0x88, 0xD2, 0xC6, 0x3A, 0x04, 0x1B, 0xC5, 0xB4,
+ 0x4F, 0x9E, 0xF1, 0x01, 0x2A, 0x2B, 0x58, 0x8F,
+ 0x3C, 0xD1, 0x1F, 0x05, 0x03, 0x3A, 0xC4, 0xC6,
+ 0x0C, 0x2E, 0xF6, 0xAB, 0x40, 0x30, 0xFE, 0x82,
+ 0x96, 0x24, 0x8D, 0xF1, 0x63, 0xF4, 0x49, 0x52 },
+ { 0x66, 0x17, 0x17, 0x8E, 0x94, 0x1F, 0x02, 0x0D,
+ 0x35, 0x1E, 0x2F, 0x25, 0x4E, 0x8F, 0xD3, 0x2C,
+ 0x60, 0x24, 0x20, 0xFE, 0xB0, 0xB8, 0xFB, 0x9A,
+ 0xDC, 0xCE, 0xBB, 0x82, 0x46, 0x1E, 0x99, 0xC5,
+ 0xA6, 0x78, 0xCC, 0x31, 0xE7, 0x99, 0x17, 0x6D,
+ 0x38, 0x60, 0xE6, 0x11, 0x0C, 0x46, 0x52, 0x3E },
+
+ /*
+ * HMAC-SHA-512 test vectors
+ */
+ { 0x87, 0xAA, 0x7C, 0xDE, 0xA5, 0xEF, 0x61, 0x9D,
+ 0x4F, 0xF0, 0xB4, 0x24, 0x1A, 0x1D, 0x6C, 0xB0,
+ 0x23, 0x79, 0xF4, 0xE2, 0xCE, 0x4E, 0xC2, 0x78,
+ 0x7A, 0xD0, 0xB3, 0x05, 0x45, 0xE1, 0x7C, 0xDE,
+ 0xDA, 0xA8, 0x33, 0xB7, 0xD6, 0xB8, 0xA7, 0x02,
+ 0x03, 0x8B, 0x27, 0x4E, 0xAE, 0xA3, 0xF4, 0xE4,
+ 0xBE, 0x9D, 0x91, 0x4E, 0xEB, 0x61, 0xF1, 0x70,
+ 0x2E, 0x69, 0x6C, 0x20, 0x3A, 0x12, 0x68, 0x54 },
+ { 0x16, 0x4B, 0x7A, 0x7B, 0xFC, 0xF8, 0x19, 0xE2,
+ 0xE3, 0x95, 0xFB, 0xE7, 0x3B, 0x56, 0xE0, 0xA3,
+ 0x87, 0xBD, 0x64, 0x22, 0x2E, 0x83, 0x1F, 0xD6,
+ 0x10, 0x27, 0x0C, 0xD7, 0xEA, 0x25, 0x05, 0x54,
+ 0x97, 0x58, 0xBF, 0x75, 0xC0, 0x5A, 0x99, 0x4A,
+ 0x6D, 0x03, 0x4F, 0x65, 0xF8, 0xF0, 0xE6, 0xFD,
+ 0xCA, 0xEA, 0xB1, 0xA3, 0x4D, 0x4A, 0x6B, 0x4B,
+ 0x63, 0x6E, 0x07, 0x0A, 0x38, 0xBC, 0xE7, 0x37 },
+ { 0xFA, 0x73, 0xB0, 0x08, 0x9D, 0x56, 0xA2, 0x84,
+ 0xEF, 0xB0, 0xF0, 0x75, 0x6C, 0x89, 0x0B, 0xE9,
+ 0xB1, 0xB5, 0xDB, 0xDD, 0x8E, 0xE8, 0x1A, 0x36,
+ 0x55, 0xF8, 0x3E, 0x33, 0xB2, 0x27, 0x9D, 0x39,
+ 0xBF, 0x3E, 0x84, 0x82, 0x79, 0xA7, 0x22, 0xC8,
+ 0x06, 0xB4, 0x85, 0xA4, 0x7E, 0x67, 0xC8, 0x07,
+ 0xB9, 0x46, 0xA3, 0x37, 0xBE, 0xE8, 0x94, 0x26,
+ 0x74, 0x27, 0x88, 0x59, 0xE1, 0x32, 0x92, 0xFB },
+ { 0xB0, 0xBA, 0x46, 0x56, 0x37, 0x45, 0x8C, 0x69,
+ 0x90, 0xE5, 0xA8, 0xC5, 0xF6, 0x1D, 0x4A, 0xF7,
+ 0xE5, 0x76, 0xD9, 0x7F, 0xF9, 0x4B, 0x87, 0x2D,
+ 0xE7, 0x6F, 0x80, 0x50, 0x36, 0x1E, 0xE3, 0xDB,
+ 0xA9, 0x1C, 0xA5, 0xC1, 0x1A, 0xA2, 0x5E, 0xB4,
+ 0xD6, 0x79, 0x27, 0x5C, 0xC5, 0x78, 0x80, 0x63,
+ 0xA5, 0xF1, 0x97, 0x41, 0x12, 0x0C, 0x4F, 0x2D,
+ 0xE2, 0xAD, 0xEB, 0xEB, 0x10, 0xA2, 0x98, 0xDD },
+ { 0x41, 0x5F, 0xAD, 0x62, 0x71, 0x58, 0x0A, 0x53,
+ 0x1D, 0x41, 0x79, 0xBC, 0x89, 0x1D, 0x87, 0xA6 },
+ { 0x80, 0xB2, 0x42, 0x63, 0xC7, 0xC1, 0xA3, 0xEB,
+ 0xB7, 0x14, 0x93, 0xC1, 0xDD, 0x7B, 0xE8, 0xB4,
+ 0x9B, 0x46, 0xD1, 0xF4, 0x1B, 0x4A, 0xEE, 0xC1,
+ 0x12, 0x1B, 0x01, 0x37, 0x83, 0xF8, 0xF3, 0x52,
+ 0x6B, 0x56, 0xD0, 0x37, 0xE0, 0x5F, 0x25, 0x98,
+ 0xBD, 0x0F, 0xD2, 0x21, 0x5D, 0x6A, 0x1E, 0x52,
+ 0x95, 0xE6, 0x4F, 0x73, 0xF6, 0x3F, 0x0A, 0xEC,
+ 0x8B, 0x91, 0x5A, 0x98, 0x5D, 0x78, 0x65, 0x98 },
+ { 0xE3, 0x7B, 0x6A, 0x77, 0x5D, 0xC8, 0x7D, 0xBA,
+ 0xA4, 0xDF, 0xA9, 0xF9, 0x6E, 0x5E, 0x3F, 0xFD,
+ 0xDE, 0xBD, 0x71, 0xF8, 0x86, 0x72, 0x89, 0x86,
+ 0x5D, 0xF5, 0xA3, 0x2D, 0x20, 0xCD, 0xC9, 0x44,
+ 0xB6, 0x02, 0x2C, 0xAC, 0x3C, 0x49, 0x82, 0xB1,
+ 0x0D, 0x5E, 0xEB, 0x55, 0xC3, 0xE4, 0xDE, 0x15,
+ 0x13, 0x46, 0x76, 0xFB, 0x6D, 0xE0, 0x44, 0x60,
+ 0x65, 0xC9, 0x74, 0x40, 0xFA, 0x8C, 0x6A, 0x58 }
+};
+
+/*
+ * Checkup routine
+ */
+int sha4_self_test( int verbose )
+{
+ int i, j, k, buflen;
+ unsigned char buf[1024];
+ unsigned char sha4sum[64];
+ sha4_context ctx;
+
+ for( i = 0; i < 6; i++ )
+ {
+ j = i % 3;
+ k = i < 3;
+
+ if( verbose != 0 )
+ printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 );
+
+ sha4_starts( &ctx, k );
+
+ if( j == 2 )
+ {
+ memset( buf, 'a', buflen = 1000 );
+
+ for( j = 0; j < 1000; j++ )
+ sha4_update( &ctx, buf, buflen );
+ }
+ else
+ sha4_update( &ctx, sha4_test_buf[j],
+ sha4_test_buflen[j] );
+
+ sha4_finish( &ctx, sha4sum );
+
+ if( memcmp( sha4sum, sha4_test_sum[i], 64 - k * 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ for( i = 0; i < 14; i++ )
+ {
+ j = i % 7;
+ k = i < 7;
+
+ if( verbose != 0 )
+ printf( " HMAC-SHA-%d test #%d: ", 512 - k * 128, j + 1 );
+
+ if( j == 5 || j == 6 )
+ {
+ memset( buf, '\xAA', buflen = 131 );
+ sha4_hmac_starts( &ctx, buf, buflen, k );
+ }
+ else
+ sha4_hmac_starts( &ctx, sha4_hmac_test_key[j],
+ sha4_hmac_test_keylen[j], k );
+
+ sha4_hmac_update( &ctx, sha4_hmac_test_buf[j],
+ sha4_hmac_test_buflen[j] );
+
+ sha4_hmac_finish( &ctx, sha4sum );
+
+ buflen = ( j == 4 ) ? 16 : 64 - k * 16;
+
+ if( memcmp( sha4sum, sha4_hmac_test_sum[i], buflen ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/sha4.h b/polarssl/sha4.h
new file mode 100644
index 0000000..e2fd55a
--- /dev/null
+++ b/polarssl/sha4.h
@@ -0,0 +1,186 @@
+/**
+ * \file sha4.h
+ *
+ * \brief SHA-384 and SHA-512 cryptographic hash function
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SHA4_H
+#define POLARSSL_SHA4_H
+
+#include "polarssl/config.h"
+
+#include
+
+#if defined(_MSC_VER) || defined(__WATCOMC__)
+ #define UL64(x) x##ui64
+ typedef unsigned __int64 uint64_t;
+#else
+ #include
+ #define UL64(x) x##ULL
+#endif
+
+#define POLARSSL_ERR_SHA4_FILE_IO_ERROR -0x007A /**< Read/write error in file. */
+
+#if !defined(POLARSSL_SHA1_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief SHA-512 context structure
+ */
+typedef struct
+{
+ uint64_t total[2]; /*!< number of bytes processed */
+ uint64_t state[8]; /*!< intermediate digest state */
+ unsigned char buffer[128]; /*!< data block being processed */
+
+ unsigned char ipad[128]; /*!< HMAC: inner padding */
+ unsigned char opad[128]; /*!< HMAC: outer padding */
+ int is384; /*!< 0 => SHA-512, else SHA-384 */
+}
+sha4_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief SHA-512 context setup
+ *
+ * \param ctx context to be initialized
+ * \param is384 0 = use SHA512, 1 = use SHA384
+ */
+void sha4_starts( sha4_context *ctx, int is384 );
+
+/**
+ * \brief SHA-512 process buffer
+ *
+ * \param ctx SHA-512 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void sha4_update( sha4_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief SHA-512 final digest
+ *
+ * \param ctx SHA-512 context
+ * \param output SHA-384/512 checksum result
+ */
+void sha4_finish( sha4_context *ctx, unsigned char output[64] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* POLARSSL_SHA4_ALT */
+#include "polarssl/sha4_alt.h"
+#endif /* POLARSSL_SHA4_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Output = SHA-512( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output SHA-384/512 checksum result
+ * \param is384 0 = use SHA512, 1 = use SHA384
+ */
+void sha4( const unsigned char *input, size_t ilen,
+ unsigned char output[64], int is384 );
+
+/**
+ * \brief Output = SHA-512( file contents )
+ *
+ * \param path input file name
+ * \param output SHA-384/512 checksum result
+ * \param is384 0 = use SHA512, 1 = use SHA384
+ *
+ * \return 0 if successful, or POLARSSL_ERR_SHA4_FILE_IO_ERROR
+ */
+int sha4_file( const char *path, unsigned char output[64], int is384 );
+
+/**
+ * \brief SHA-512 HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param is384 0 = use SHA512, 1 = use SHA384
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ */
+void sha4_hmac_starts( sha4_context *ctx, const unsigned char *key, size_t keylen,
+ int is384 );
+
+/**
+ * \brief SHA-512 HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void sha4_hmac_update( sha4_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief SHA-512 HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output SHA-384/512 HMAC checksum result
+ */
+void sha4_hmac_finish( sha4_context *ctx, unsigned char output[64] );
+
+/**
+ * \brief SHA-512 HMAC context reset
+ *
+ * \param ctx HMAC context to be reset
+ */
+void sha4_hmac_reset( sha4_context *ctx );
+
+/**
+ * \brief Output = HMAC-SHA-512( hmac key, input buffer )
+ *
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output HMAC-SHA-384/512 result
+ * \param is384 0 = use SHA512, 1 = use SHA384
+ */
+void sha4_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[64], int is384 );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int sha4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha4.h */
diff --git a/polarssl/ssl.h b/polarssl/ssl.h
new file mode 100644
index 0000000..5b2d978
--- /dev/null
+++ b/polarssl/ssl.h
@@ -0,0 +1,1140 @@
+/**
+ * \file ssl.h
+ *
+ * \brief SSL/TLS functions.
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SSL_H
+#define POLARSSL_SSL_H
+
+#include
+
+#include "polarssl/net.h"
+#include "polarssl/rsa.h"
+#include "polarssl/md5.h"
+#include "polarssl/sha1.h"
+#include "polarssl/sha2.h"
+#include "polarssl/sha4.h"
+#include "polarssl/x509.h"
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_DHM_C)
+#include "polarssl/dhm.h"
+#endif
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+#include "polarssl/zlib.h"
+#endif
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+/*
+ * SSL Error codes
+ */
+#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */
+#define POLARSSL_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */
+#define POLARSSL_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */
+#define POLARSSL_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */
+#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */
+#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */
+#define POLARSSL_ERR_SSL_NO_SESSION_FOUND -0x7400 /**< No session to recover was found. */
+#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */
+#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message.*/
+#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */
+#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key is not set, but needed. */
+#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */
+#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */
+#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */
+#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */
+#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM Read Public. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM Calculate Secret. */
+#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */
+#define POLARSSL_ERR_SSL_MALLOC_FAILED -0x7F00 /**< Memory allocation failed */
+#define POLARSSL_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /**< Hardware acceleration function returned with error */
+#define POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /**< Hardware acceleration function skipped / left alone data */
+#define POLARSSL_ERR_SSL_COMPRESSION_FAILED -0x6F00 /**< Processing of the compression / decompression failed */
+#define POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 /**< Handshake protocol not within min/max boundaries */
+
+/*
+ * Various constants
+ */
+#define SSL_MAJOR_VERSION_3 3
+#define SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */
+#define SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */
+#define SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */
+#define SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */
+
+#define SSL_IS_CLIENT 0
+#define SSL_IS_SERVER 1
+#define SSL_COMPRESS_NULL 0
+#define SSL_COMPRESS_DEFLATE 1
+
+#define SSL_VERIFY_NONE 0
+#define SSL_VERIFY_OPTIONAL 1
+#define SSL_VERIFY_REQUIRED 2
+
+#define SSL_INITIAL_HANDSHAKE 0
+#define SSL_RENEGOTIATION 1
+
+#define SSL_LEGACY_RENEGOTIATION 0
+#define SSL_SECURE_RENEGOTIATION 1
+
+#define SSL_RENEGOTIATION_DISABLED 0
+#define SSL_RENEGOTIATION_ENABLED 1
+
+#define SSL_LEGACY_NO_RENEGOTIATION 0
+#define SSL_LEGACY_ALLOW_RENEGOTIATION 1
+#define SSL_LEGACY_BREAK_HANDSHAKE 2
+
+/*
+ * Size of the input / output buffer.
+ * Note: the RFC defines the default size of SSL / TLS messages. If you
+ * change the value here, other clients / servers may not be able to
+ * communicate with you anymore. Only change this value if you control
+ * both sides of the connection and have it reduced at both sides!
+ */
+#if !defined(POLARSSL_CONFIG_OPTIONS)
+#define SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */
+#endif /* !POLARSSL_CONFIG_OPTIONS */
+
+/*
+ * Allow an extra 512 bytes for the record header
+ * and encryption overhead (counter + MAC + padding)
+ * and allow for a maximum of 1024 of compression expansion if
+ * enabled.
+ */
+#if defined(POLARSSL_ZLIB_SUPPORT)
+#define SSL_COMPRESSION_ADD 1024
+#else
+#define SSL_COMPRESSION_ADD 0
+#endif
+
+#define SSL_BUFFER_LEN (SSL_MAX_CONTENT_LEN + SSL_COMPRESSION_ADD + 512)
+
+/*
+ * Supported ciphersuites (Official IANA names)
+ */
+#define TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */
+#define TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */
+#define TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */
+#define TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */
+#define TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */
+
+#define TLS_RSA_WITH_RC4_128_MD5 0x04
+#define TLS_RSA_WITH_RC4_128_SHA 0x05
+
+#define TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A
+#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16
+
+#define TLS_RSA_WITH_AES_128_CBC_SHA 0x2F
+#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33
+#define TLS_RSA_WITH_AES_256_CBC_SHA 0x35
+#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39
+#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */
+#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */
+
+#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41
+#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45
+#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84
+#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88
+#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */
+#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */
+
+#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C
+#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D
+#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E
+#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F
+
+#define SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */
+
+/*
+ * Supported Signature and Hash algorithms (For TLS 1.2)
+ */
+#define SSL_HASH_NONE 0
+#define SSL_HASH_MD5 1
+#define SSL_HASH_SHA1 2
+#define SSL_HASH_SHA224 3
+#define SSL_HASH_SHA256 4
+#define SSL_HASH_SHA384 5
+#define SSL_HASH_SHA512 6
+
+#define SSL_SIG_RSA 1
+
+/*
+ * Client Certificate Types
+ */
+#define SSL_CERT_TYPE_RSA_SIGN 1
+
+/*
+ * Message, alert and handshake types
+ */
+#define SSL_MSG_CHANGE_CIPHER_SPEC 20
+#define SSL_MSG_ALERT 21
+#define SSL_MSG_HANDSHAKE 22
+#define SSL_MSG_APPLICATION_DATA 23
+
+#define SSL_ALERT_LEVEL_WARNING 1
+#define SSL_ALERT_LEVEL_FATAL 2
+
+#define SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */
+#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */
+#define SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */
+#define SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */
+#define SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */
+#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */
+#define SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */
+#define SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */
+#define SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */
+#define SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */
+#define SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */
+#define SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */
+#define SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */
+#define SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */
+#define SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */
+#define SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */
+#define SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */
+#define SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */
+#define SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */
+#define SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */
+#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */
+#define SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */
+#define SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */
+#define SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */
+#define SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */
+#define SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */
+
+#define SSL_HS_HELLO_REQUEST 0
+#define SSL_HS_CLIENT_HELLO 1
+#define SSL_HS_SERVER_HELLO 2
+#define SSL_HS_CERTIFICATE 11
+#define SSL_HS_SERVER_KEY_EXCHANGE 12
+#define SSL_HS_CERTIFICATE_REQUEST 13
+#define SSL_HS_SERVER_HELLO_DONE 14
+#define SSL_HS_CERTIFICATE_VERIFY 15
+#define SSL_HS_CLIENT_KEY_EXCHANGE 16
+#define SSL_HS_FINISHED 20
+
+/*
+ * TLS extensions
+ */
+#define TLS_EXT_SERVERNAME 0
+#define TLS_EXT_SERVERNAME_HOSTNAME 0
+
+#define TLS_EXT_SIG_ALG 13
+
+#define TLS_EXT_RENEGOTIATION_INFO 0xFF01
+
+
+/*
+ * Generic function pointers for allowing external RSA private key
+ * implementations.
+ */
+typedef int (*rsa_decrypt_func)( void *ctx, int mode, size_t *olen,
+ const unsigned char *input, unsigned char *output,
+ size_t output_max_len );
+typedef int (*rsa_sign_func)( void *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ int mode, int hash_id, unsigned int hashlen,
+ const unsigned char *hash, unsigned char *sig );
+typedef size_t (*rsa_key_len_func)( void *ctx );
+
+/*
+ * SSL state machine
+ */
+typedef enum
+{
+ SSL_HELLO_REQUEST,
+ SSL_CLIENT_HELLO,
+ SSL_SERVER_HELLO,
+ SSL_SERVER_CERTIFICATE,
+ SSL_SERVER_KEY_EXCHANGE,
+ SSL_CERTIFICATE_REQUEST,
+ SSL_SERVER_HELLO_DONE,
+ SSL_CLIENT_CERTIFICATE,
+ SSL_CLIENT_KEY_EXCHANGE,
+ SSL_CERTIFICATE_VERIFY,
+ SSL_CLIENT_CHANGE_CIPHER_SPEC,
+ SSL_CLIENT_FINISHED,
+ SSL_SERVER_CHANGE_CIPHER_SPEC,
+ SSL_SERVER_FINISHED,
+ SSL_FLUSH_BUFFERS,
+ SSL_HANDSHAKE_WRAPUP,
+ SSL_HANDSHAKE_OVER
+}
+ssl_states;
+
+typedef struct _ssl_session ssl_session;
+typedef struct _ssl_context ssl_context;
+typedef struct _ssl_transform ssl_transform;
+typedef struct _ssl_handshake_params ssl_handshake_params;
+
+/*
+ * This structure is used for storing current session data.
+ */
+struct _ssl_session
+{
+ time_t start; /*!< starting time */
+ int ciphersuite; /*!< chosen ciphersuite */
+ int compression; /*!< chosen compression */
+ size_t length; /*!< session id length */
+ unsigned char id[32]; /*!< session identifier */
+ unsigned char master[48]; /*!< the master secret */
+ x509_cert *peer_cert; /*!< peer X.509 cert chain */
+};
+
+/*
+ * This structure contains a full set of runtime transform parameters
+ * either in negotiation or active.
+ */
+struct _ssl_transform
+{
+ /*
+ * Session specific crypto layer
+ */
+ unsigned int keylen; /*!< symmetric key length */
+ size_t minlen; /*!< min. ciphertext length */
+ size_t ivlen; /*!< IV length */
+ size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */
+ size_t maclen; /*!< MAC length */
+
+ unsigned char iv_enc[16]; /*!< IV (encryption) */
+ unsigned char iv_dec[16]; /*!< IV (decryption) */
+
+ unsigned char mac_enc[32]; /*!< MAC (encryption) */
+ unsigned char mac_dec[32]; /*!< MAC (decryption) */
+
+ uint32_t ctx_enc[136]; /*!< encryption context */
+ uint32_t ctx_dec[136]; /*!< decryption context */
+
+ /*
+ * Session specific compression layer
+ */
+#if defined(POLARSSL_ZLIB_SUPPORT)
+ z_stream ctx_deflate; /*!< compression context */
+ z_stream ctx_inflate; /*!< decompression context */
+#endif
+};
+
+/*
+ * This structure contains the parameters only needed during handshake.
+ */
+struct _ssl_handshake_params
+{
+ /*
+ * Handshake specific crypto variables
+ */
+ int sig_alg; /*!< Signature algorithm */
+ int cert_type; /*!< Requested cert type */
+ int verify_sig_alg; /*!< Signature algorithm for verify */
+#if defined(POLARSSL_DHM_C)
+ dhm_context dhm_ctx; /*!< DHM key exchange */
+#endif
+
+ /*
+ * Checksum contexts
+ */
+ md5_context fin_md5;
+ sha1_context fin_sha1;
+ sha2_context fin_sha2;
+ sha4_context fin_sha4;
+
+ void (*update_checksum)(ssl_context *, unsigned char *, size_t);
+ void (*calc_verify)(ssl_context *, unsigned char *);
+ void (*calc_finished)(ssl_context *, unsigned char *, int);
+ int (*tls_prf)(unsigned char *, size_t, char *,
+ unsigned char *, size_t,
+ unsigned char *, size_t);
+
+ size_t pmslen; /*!< premaster length */
+
+ unsigned char randbytes[64]; /*!< random bytes */
+ unsigned char premaster[POLARSSL_MPI_MAX_SIZE];
+ /*!< premaster secret */
+
+ int resume; /*!< session resume indicator*/
+};
+
+struct _ssl_context
+{
+ /*
+ * Miscellaneous
+ */
+ int state; /*!< SSL handshake: current state */
+ int renegotiation; /*!< Initial or renegotiation */
+
+ int major_ver; /*!< equal to SSL_MAJOR_VERSION_3 */
+ int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */
+
+ int max_major_ver; /*!< max. major version from client */
+ int max_minor_ver; /*!< max. minor version from client */
+ int min_major_ver; /*!< min. major version accepted */
+ int min_minor_ver; /*!< min. minor version accepted */
+
+ /*
+ * Callbacks (RNG, debug, I/O, verification)
+ */
+ int (*f_rng)(void *, unsigned char *, size_t);
+ void (*f_dbg)(void *, int, const char *);
+ int (*f_recv)(void *, unsigned char *, size_t);
+ int (*f_send)(void *, const unsigned char *, size_t);
+ int (*f_vrfy)(void *, x509_cert *, int, int *);
+ int (*f_get_cache)(void *, ssl_session *);
+ int (*f_set_cache)(void *, const ssl_session *);
+ int (*f_sni)(void *, ssl_context *, const unsigned char *, size_t);
+
+ void *p_rng; /*!< context for the RNG function */
+ void *p_dbg; /*!< context for the debug function */
+ void *p_recv; /*!< context for reading operations */
+ void *p_send; /*!< context for writing operations */
+ void *p_vrfy; /*!< context for verification */
+ void *p_get_cache; /*!< context for cache retrieval */
+ void *p_set_cache; /*!< context for cache store */
+ void *p_sni; /*!< context for SNI extension */
+ void *p_hw_data; /*!< context for HW acceleration */
+
+ /*
+ * Session layer
+ */
+ ssl_session *session_in; /*!< current session data (in) */
+ ssl_session *session_out; /*!< current session data (out) */
+ ssl_session *session; /*!< negotiated session data */
+ ssl_session *session_negotiate; /*!< session data in negotiation */
+
+ ssl_handshake_params *handshake; /*!< params required only during
+ the handshake process */
+
+ /*
+ * Record layer transformations
+ */
+ ssl_transform *transform_in; /*!< current transform params (in) */
+ ssl_transform *transform_out; /*!< current transform params (in) */
+ ssl_transform *transform; /*!< negotiated transform params */
+ ssl_transform *transform_negotiate; /*!< transform params in negotiation */
+
+ /*
+ * Record layer (incoming data)
+ */
+ unsigned char *in_ctr; /*!< 64-bit incoming message counter */
+ unsigned char *in_hdr; /*!< 5-byte record header (in_ctr+8) */
+ unsigned char *in_msg; /*!< the message contents (in_hdr+5) */
+ unsigned char *in_offt; /*!< read offset in application data */
+
+ int in_msgtype; /*!< record header: message type */
+ size_t in_msglen; /*!< record header: message length */
+ size_t in_left; /*!< amount of data read so far */
+
+ size_t in_hslen; /*!< current handshake message length */
+ int nb_zero; /*!< # of 0-length encrypted messages */
+
+ /*
+ * Record layer (outgoing data)
+ */
+ unsigned char *out_ctr; /*!< 64-bit outgoing message counter */
+ unsigned char *out_hdr; /*!< 5-byte record header (out_ctr+8) */
+ unsigned char *out_msg; /*!< the message contents (out_hdr+32)*/
+
+ int out_msgtype; /*!< record header: message type */
+ size_t out_msglen; /*!< record header: message length */
+ size_t out_left; /*!< amount of data not yet written */
+
+ /*
+ * PKI layer
+ */
+ void *rsa_key; /*!< own RSA private key */
+ rsa_decrypt_func rsa_decrypt; /*!< function for RSA decrypt*/
+ rsa_sign_func rsa_sign; /*!< function for RSA sign */
+ rsa_key_len_func rsa_key_len; /*!< function for RSA key len*/
+
+ x509_cert *own_cert; /*!< own X.509 certificate */
+ x509_cert *ca_chain; /*!< own trusted CA chain */
+ x509_crl *ca_crl; /*!< trusted CA CRLs */
+ const char *peer_cn; /*!< expected peer CN */
+
+ /*
+ * User settings
+ */
+ int endpoint; /*!< 0: client, 1: server */
+ int authmode; /*!< verification mode */
+ int client_auth; /*!< flag for client auth. */
+ int verify_result; /*!< verification result */
+ int disable_renegotiation; /*!< enable/disable renegotiation */
+ int allow_legacy_renegotiation; /*!< allow legacy renegotiation */
+ const int **ciphersuites; /*!< allowed ciphersuites / version */
+
+#if defined(POLARSSL_DHM_C)
+ mpi dhm_P; /*!< prime modulus for DHM */
+ mpi dhm_G; /*!< generator for DHM */
+#endif
+
+ /*
+ * TLS extensions
+ */
+ unsigned char *hostname;
+ size_t hostname_len;
+
+ /*
+ * Secure renegotiation
+ */
+ int secure_renegotiation; /*!< does peer support legacy or
+ secure renegotiation */
+ size_t verify_data_len; /*!< length of verify data stored */
+ char own_verify_data[36]; /*!< previous handshake verify data */
+ char peer_verify_data[36]; /*!< previous handshake verify data */
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const int ssl_default_ciphersuites[];
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+extern int (*ssl_hw_record_init)(ssl_context *ssl,
+ const unsigned char *key_enc, const unsigned char *key_dec,
+ const unsigned char *iv_enc, const unsigned char *iv_dec,
+ const unsigned char *mac_enc, const unsigned char *mac_dec);
+extern int (*ssl_hw_record_reset)(ssl_context *ssl);
+extern int (*ssl_hw_record_write)(ssl_context *ssl);
+extern int (*ssl_hw_record_read)(ssl_context *ssl);
+extern int (*ssl_hw_record_finish)(ssl_context *ssl);
+#endif
+
+/**
+ * \brief Returns the list of ciphersuites supported by the SSL/TLS module.
+ *
+ * \return a statically allocated array of ciphersuites, the last
+ * entry is 0.
+ */
+static inline const int *ssl_list_ciphersuites( void )
+{
+ return ssl_default_ciphersuites;
+}
+
+/**
+ * \brief Return the name of the ciphersuite associated with the given
+ * ID
+ *
+ * \param ciphersuite_id SSL ciphersuite ID
+ *
+ * \return a string containing the ciphersuite name
+ */
+const char *ssl_get_ciphersuite_name( const int ciphersuite_id );
+
+/**
+ * \brief Return the ID of the ciphersuite associated with the given
+ * name
+ *
+ * \param ciphersuite_name SSL ciphersuite name
+ *
+ * \return the ID with the ciphersuite or 0 if not found
+ */
+int ssl_get_ciphersuite_id( const char *ciphersuite_name );
+
+/**
+ * \brief Initialize an SSL context
+ *
+ * \param ssl SSL context
+ *
+ * \return 0 if successful, or POLARSSL_ERR_SSL_MALLOC_FAILED if
+ * memory allocation failed
+ */
+int ssl_init( ssl_context *ssl );
+
+/**
+ * \brief Reset an already initialized SSL context for re-use
+ * while retaining application-set variables, function
+ * pointers and data.
+ *
+ * \param ssl SSL context
+ * \return 0 if successful, or POLASSL_ERR_SSL_MALLOC_FAILED,
+ POLARSSL_ERR_SSL_HW_ACCEL_FAILED or
+ * POLARSSL_ERR_SSL_COMPRESSION_FAILED
+ */
+int ssl_session_reset( ssl_context *ssl );
+
+/**
+ * \brief Set the current endpoint type
+ *
+ * \param ssl SSL context
+ * \param endpoint must be SSL_IS_CLIENT or SSL_IS_SERVER
+ */
+void ssl_set_endpoint( ssl_context *ssl, int endpoint );
+
+/**
+ * \brief Set the certificate verification mode
+ *
+ * \param ssl SSL context
+ * \param authmode can be:
+ *
+ * SSL_VERIFY_NONE: peer certificate is not checked (default),
+ * this is insecure and SHOULD be avoided.
+ *
+ * SSL_VERIFY_OPTIONAL: peer certificate is checked, however the
+ * handshake continues even if verification failed;
+ * ssl_get_verify_result() can be called after the
+ * handshake is complete.
+ *
+ * SSL_VERIFY_REQUIRED: peer *must* present a valid certificate,
+ * handshake is aborted if verification failed.
+ */
+void ssl_set_authmode( ssl_context *ssl, int authmode );
+
+/**
+ * \brief Set the verification callback (Optional).
+ *
+ * If set, the verify callback is called for each
+ * certificate in the chain. For implementation
+ * information, please see \c x509parse_verify()
+ *
+ * \param ssl SSL context
+ * \param f_vrfy verification function
+ * \param p_vrfy verification parameter
+ */
+void ssl_set_verify( ssl_context *ssl,
+ int (*f_vrfy)(void *, x509_cert *, int, int *),
+ void *p_vrfy );
+
+/**
+ * \brief Set the random number generator callback
+ *
+ * \param ssl SSL context
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ */
+void ssl_set_rng( ssl_context *ssl,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Set the debug callback
+ *
+ * \param ssl SSL context
+ * \param f_dbg debug function
+ * \param p_dbg debug parameter
+ */
+void ssl_set_dbg( ssl_context *ssl,
+ void (*f_dbg)(void *, int, const char *),
+ void *p_dbg );
+
+/**
+ * \brief Set the underlying BIO read and write callbacks
+ *
+ * \param ssl SSL context
+ * \param f_recv read callback
+ * \param p_recv read parameter
+ * \param f_send write callback
+ * \param p_send write parameter
+ */
+void ssl_set_bio( ssl_context *ssl,
+ int (*f_recv)(void *, unsigned char *, size_t), void *p_recv,
+ int (*f_send)(void *, const unsigned char *, size_t), void *p_send );
+
+/**
+ * \brief Set the session cache callbacks (server-side only)
+ * If not set, no session resuming is done.
+ *
+ * The session cache has the responsibility to check for stale
+ * entries based on timeout. See RFC 5246 for recommendations.
+ *
+ * Warning: session.peer_cert is cleared by the SSL/TLS layer on
+ * connection shutdown, so do not cache the pointer! Either set
+ * it to NULL or make a full copy of the certificate.
+ *
+ * The get callback is called once during the initial handshake
+ * to enable session resuming. The get function has the
+ * following parameters: (void *parameter, ssl_session *session)
+ * If a valid entry is found, it should fill the master of
+ * the session object with the cached values and return 0,
+ * return 1 otherwise. Optionally peer_cert can be set as well
+ * if it is properly present in cache entry.
+ *
+ * The set callback is called once during the initial handshake
+ * to enable session resuming after the entire handshake has
+ * been finished. The set function has the following parameters:
+ * (void *parameter, const ssl_session *session). The function
+ * should create a cache entry for future retrieval based on
+ * the data in the session structure and should keep in mind
+ * that the ssl_session object presented (and all its referenced
+ * data) is cleared by the SSL/TLS layer when the connection is
+ * terminated. It is recommended to add metadata to determine if
+ * an entry is still valid in the future. Return 0 if
+ * successfully cached, return 1 otherwise.
+ *
+ * \param ssl SSL context
+ * \param f_get_cache session get callback
+ * \param p_get_cache session get parameter
+ * \param f_set_cache session set callback
+ * \param p_set_cache session set parameter
+ */
+void ssl_set_session_cache( ssl_context *ssl,
+ int (*f_get_cache)(void *, ssl_session *), void *p_get_cache,
+ int (*f_set_cache)(void *, const ssl_session *), void *p_set_cache );
+
+/**
+ * \brief Request resumption of session (client-side only)
+ * Session data is copied from presented session structure.
+ *
+ * Warning: session.peer_cert is cleared by the SSL/TLS layer on
+ * connection shutdown, so do not cache the pointer! Either set
+ * it to NULL or make a full copy of the certificate when
+ * storing the session for use in this function.
+ *
+ * \param ssl SSL context
+ * \param session session context
+ */
+void ssl_set_session( ssl_context *ssl, const ssl_session *session );
+
+/**
+ * \brief Set the list of allowed ciphersuites
+ * (Default: ssl_default_ciphersuites)
+ * (Overrides all version specific lists)
+ *
+ * \param ssl SSL context
+ * \param ciphersuites 0-terminated list of allowed ciphersuites
+ */
+void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites );
+
+/**
+ * \brief Set the list of allowed ciphersuites for a specific
+ * version of the protocol.
+ * (Default: ssl_default_ciphersuites)
+ * (Only useful on the server side)
+ *
+ * \param ssl SSL context
+ * \param ciphersuites 0-terminated list of allowed ciphersuites
+ * \param major Major version number (only SSL_MAJOR_VERSION_3
+ * supported)
+ * \param minor Minor version number (SSL_MINOR_VERSION_0,
+ * SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2,
+ * SSL_MINOR_VERSION_3 supported)
+ */
+void ssl_set_ciphersuites_for_version( ssl_context *ssl,
+ const int *ciphersuites,
+ int major, int minor );
+
+/**
+ * \brief Set the data required to verify peer certificate
+ *
+ * \param ssl SSL context
+ * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs)
+ * \param ca_crl trusted CA CRLs
+ * \param peer_cn expected peer CommonName (or NULL)
+ */
+void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain,
+ x509_crl *ca_crl, const char *peer_cn );
+
+/**
+ * \brief Set own certificate chain and private key
+ *
+ * Note: own_cert should contain IN order from the bottom
+ * up your certificate chain. The top certificate (self-signed)
+ * can be omitted.
+ *
+ * \param ssl SSL context
+ * \param own_cert own public certificate chain
+ * \param rsa_key own private RSA key
+ */
+void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert,
+ rsa_context *rsa_key );
+
+/**
+ * \brief Set own certificate and alternate non-PolarSSL private
+ * key and handling callbacks, such as the PKCS#11 wrappers
+ * or any other external private key handler.
+ * (see the respective RSA functions in rsa.h for documentation
+ * of the callback parameters, with the only change being
+ * that the rsa_context * is a void * in the callbacks)
+ *
+ * Note: own_cert should contain IN order from the bottom
+ * up your certificate chain. The top certificate (self-signed)
+ * can be omitted.
+ *
+ * \param ssl SSL context
+ * \param own_cert own public certificate chain
+ * \param rsa_key alternate implementation private RSA key
+ * \param rsa_decrypt_func alternate implementation of \c rsa_pkcs1_decrypt()
+ * \param rsa_sign_func alternate implementation of \c rsa_pkcs1_sign()
+ * \param rsa_key_len_func function returning length of RSA key in bytes
+ */
+void ssl_set_own_cert_alt( ssl_context *ssl, x509_cert *own_cert,
+ void *rsa_key,
+ rsa_decrypt_func rsa_decrypt,
+ rsa_sign_func rsa_sign,
+ rsa_key_len_func rsa_key_len );
+
+#if defined(POLARSSL_DHM_C)
+/**
+ * \brief Set the Diffie-Hellman public P and G values,
+ * read as hexadecimal strings (server-side only)
+ * (Default: POLARSSL_DHM_RFC5114_MODP_1024_[PG])
+ *
+ * \param ssl SSL context
+ * \param dhm_P Diffie-Hellman-Merkle modulus
+ * \param dhm_G Diffie-Hellman-Merkle generator
+ *
+ * \return 0 if successful
+ */
+int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G );
+
+/**
+ * \brief Set the Diffie-Hellman public P and G values,
+ * read from existing context (server-side only)
+ *
+ * \param ssl SSL context
+ * \param dhm_ctx Diffie-Hellman-Merkle context
+ *
+ * \return 0 if successful
+ */
+int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx );
+#endif
+
+/**
+ * \brief Set hostname for ServerName TLS extension
+ * (client-side only)
+ *
+ *
+ * \param ssl SSL context
+ * \param hostname the server hostname
+ *
+ * \return 0 if successful or POLARSSL_ERR_SSL_MALLOC_FAILED
+ */
+int ssl_set_hostname( ssl_context *ssl, const char *hostname );
+
+/**
+ * \brief Set server side ServerName TLS extension callback
+ * (optional, server-side only).
+ *
+ * If set, the ServerName callback is called whenever the
+ * server receives a ServerName TLS extension from the client
+ * during a handshake. The ServerName callback has the
+ * following parameters: (void *parameter, ssl_context *ssl,
+ * const unsigned char *hostname, size_t len). If a suitable
+ * certificate is found, the callback should set the
+ * certificate and key to use with ssl_set_own_cert() (and
+ * possibly adjust the CA chain as well) and return 0. The
+ * callback should return -1 to abort the handshake at this
+ * point.
+ *
+ * \param ssl SSL context
+ * \param f_sni verification function
+ * \param p_sni verification parameter
+ */
+void ssl_set_sni( ssl_context *ssl,
+ int (*f_sni)(void *, ssl_context *, const unsigned char *,
+ size_t),
+ void *p_sni );
+
+/**
+ * \brief Set the maximum supported version sent from the client side
+ *
+ * \param ssl SSL context
+ * \param major Major version number (only SSL_MAJOR_VERSION_3 supported)
+ * \param minor Minor version number (SSL_MINOR_VERSION_0,
+ * SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2,
+ * SSL_MINOR_VERSION_3 supported)
+ */
+void ssl_set_max_version( ssl_context *ssl, int major, int minor );
+
+
+/**
+ * \brief Set the minimum accepted SSL/TLS protocol version
+ * (Default: SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0)
+ *
+ * \param ssl SSL context
+ * \param major Major version number (only SSL_MAJOR_VERSION_3 supported)
+ * \param minor Minor version number (SSL_MINOR_VERSION_0,
+ * SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2,
+ * SSL_MINOR_VERSION_3 supported)
+ */
+void ssl_set_min_version( ssl_context *ssl, int major, int minor );
+
+/**
+ * \brief Enable / Disable renegotiation support for connection when
+ * initiated by peer
+ * (Default: SSL_RENEGOTIATION_DISABLED)
+ *
+ * Note: A server with support enabled is more vulnerable for a
+ * resource DoS by a malicious client. You should enable this on
+ * a client to enable server-initiated renegotiation.
+ *
+ * \param ssl SSL context
+ * \param renegotiation Enable or disable (SSL_RENEGOTIATION_ENABLED or
+ * SSL_RENEGOTIATION_DISABLED)
+ */
+void ssl_set_renegotiation( ssl_context *ssl, int renegotiation );
+
+/**
+ * \brief Prevent or allow legacy renegotiation.
+ * (Default: SSL_LEGACY_NO_RENEGOTIATION)
+ *
+ * SSL_LEGACY_NO_RENEGOTIATION allows connections to
+ * be established even if the peer does not support
+ * secure renegotiation, but does not allow renegotiation
+ * to take place if not secure.
+ * (Interoperable and secure option)
+ *
+ * SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations
+ * with non-upgraded peers. Allowing legacy renegotiation
+ * makes the connection vulnerable to specific man in the
+ * middle attacks. (See RFC 5746)
+ * (Most interoperable and least secure option)
+ *
+ * SSL_LEGACY_BREAK_HANDSHAKE breaks off connections
+ * if peer does not support secure renegotiation. Results
+ * in interoperability issues with non-upgraded peers
+ * that do not support renegotiation altogether.
+ * (Most secure option, interoperability issues)
+ *
+ * \param ssl SSL context
+ * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION,
+ * SSL_ALLOW_LEGACY_RENEGOTIATION or
+ * SSL_LEGACY_BREAK_HANDSHAKE)
+ */
+void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy );
+
+/**
+ * \brief Return the number of data bytes available to read
+ *
+ * \param ssl SSL context
+ *
+ * \return how many bytes are available in the read buffer
+ */
+size_t ssl_get_bytes_avail( const ssl_context *ssl );
+
+/**
+ * \brief Return the result of the certificate verification
+ *
+ * \param ssl SSL context
+ *
+ * \return 0 if successful, or a combination of:
+ * BADCERT_EXPIRED
+ * BADCERT_REVOKED
+ * BADCERT_CN_MISMATCH
+ * BADCERT_NOT_TRUSTED
+ */
+int ssl_get_verify_result( const ssl_context *ssl );
+
+/**
+ * \brief Return the name of the current ciphersuite
+ *
+ * \param ssl SSL context
+ *
+ * \return a string containing the ciphersuite name
+ */
+const char *ssl_get_ciphersuite( const ssl_context *ssl );
+
+/**
+ * \brief Return the current SSL version (SSLv3/TLSv1/etc)
+ *
+ * \param ssl SSL context
+ *
+ * \return a string containing the SSL version
+ */
+const char *ssl_get_version( const ssl_context *ssl );
+
+/**
+ * \brief Return the peer certificate from the current connection
+ *
+ * Note: Can be NULL in case no certificate was sent during
+ * the handshake. Different calls for the same connection can
+ * return the same or different pointers for the same
+ * certificate and even a different certificate altogether.
+ * The peer cert CAN change in a single connection if
+ * renegotiation is performed.
+ *
+ * \param ssl SSL context
+ *
+ * \return the current peer certificate
+ */
+const x509_cert *ssl_get_peer_cert( const ssl_context *ssl );
+
+/**
+ * \brief Perform the SSL handshake
+ *
+ * \param ssl SSL context
+ *
+ * \return 0 if successful, POLARSSL_ERR_NET_WANT_READ,
+ * POLARSSL_ERR_NET_WANT_WRITE, or a specific SSL error code.
+ */
+int ssl_handshake( ssl_context *ssl );
+
+/**
+ * \brief Perform a single step of the SSL handshake
+ *
+ * Note: the state of the context (ssl->state) will be at
+ * the following state after execution of this function.
+ * Do not call this function if state is SSL_HANDSHAKE_OVER.
+ *
+ * \param ssl SSL context
+ *
+ * \return 0 if successful, POLARSSL_ERR_NET_WANT_READ,
+ * POLARSSL_ERR_NET_WANT_WRITE, or a specific SSL error code.
+ */
+int ssl_handshake_step( ssl_context *ssl );
+
+/**
+ * \brief Perform an SSL renegotiation on the running connection
+ *
+ * \param ssl SSL context
+ *
+ * \return 0 if succesful, or any ssl_handshake() return value.
+ */
+int ssl_renegotiate( ssl_context *ssl );
+
+/**
+ * \brief Read at most 'len' application data bytes
+ *
+ * \param ssl SSL context
+ * \param buf buffer that will hold the data
+ * \param len how many bytes must be read
+ *
+ * \return This function returns the number of bytes read, 0 for EOF,
+ * or a negative error code.
+ */
+int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len );
+
+/**
+ * \brief Write exactly 'len' application data bytes
+ *
+ * \param ssl SSL context
+ * \param buf buffer holding the data
+ * \param len how many bytes must be written
+ *
+ * \return This function returns the number of bytes written,
+ * or a negative error code.
+ *
+ * \note When this function returns POLARSSL_ERR_NET_WANT_WRITE,
+ * it must be called later with the *same* arguments,
+ * until it returns a positive value.
+ */
+int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len );
+
+/**
+ * \brief Send an alert message
+ *
+ * \param ssl SSL context
+ * \param level The alert level of the message
+ * (SSL_ALERT_LEVEL_WARNING or SSL_ALERT_LEVEL_FATAL)
+ * \param message The alert message (SSL_ALERT_MSG_*)
+ *
+ * \return 0 if successful, or a specific SSL error code.
+ */
+int ssl_send_alert_message( ssl_context *ssl,
+ unsigned char level,
+ unsigned char message );
+/**
+ * \brief Notify the peer that the connection is being closed
+ *
+ * \param ssl SSL context
+ */
+int ssl_close_notify( ssl_context *ssl );
+
+/**
+ * \brief Free referenced items in an SSL context and clear memory
+ *
+ * \param ssl SSL context
+ */
+void ssl_free( ssl_context *ssl );
+
+/**
+ * \brief Free referenced items in an SSL session including the
+ * peer certificate and clear memory
+ *
+ * \param session SSL session
+ */
+void ssl_session_free( ssl_session *session );
+
+/**
+ * \brief Free referenced items in an SSL transform context and clear
+ * memory
+ *
+ * \param transform SSL transform context
+ */
+void ssl_transform_free( ssl_transform *transform );
+
+/**
+ * \brief Free referenced items in an SSL handshake context and clear
+ * memory
+ *
+ * \param handshake SSL handshake context
+ */
+void ssl_handshake_free( ssl_handshake_params *handshake );
+
+/*
+ * Internal functions (do not call directly)
+ */
+int ssl_handshake_client_step( ssl_context *ssl );
+int ssl_handshake_server_step( ssl_context *ssl );
+void ssl_handshake_wrapup( ssl_context *ssl );
+
+int ssl_send_fatal_handshake_failure( ssl_context *ssl );
+
+int ssl_derive_keys( ssl_context *ssl );
+
+int ssl_read_record( ssl_context *ssl );
+/**
+ * \return 0 if successful, POLARSSL_ERR_SSL_CONN_EOF on EOF or
+ * another negative error code.
+ */
+int ssl_fetch_input( ssl_context *ssl, size_t nb_want );
+
+int ssl_write_record( ssl_context *ssl );
+int ssl_flush_output( ssl_context *ssl );
+
+int ssl_parse_certificate( ssl_context *ssl );
+int ssl_write_certificate( ssl_context *ssl );
+
+int ssl_parse_change_cipher_spec( ssl_context *ssl );
+int ssl_write_change_cipher_spec( ssl_context *ssl );
+
+int ssl_parse_finished( ssl_context *ssl );
+int ssl_write_finished( ssl_context *ssl );
+
+void ssl_optimize_checksum( ssl_context *ssl, int ciphersuite );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ssl.h */
diff --git a/polarssl/ssl_cache.c b/polarssl/ssl_cache.c
new file mode 100644
index 0000000..f5686be
--- /dev/null
+++ b/polarssl/ssl_cache.c
@@ -0,0 +1,221 @@
+/*
+ * SSL session cache implementation
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * These session callbacks use a simple chained list
+ * to store and retrieve the session information.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SSL_CACHE_C)
+
+#include "polarssl/ssl_cache.h"
+
+#include
+
+void ssl_cache_init( ssl_cache_context *cache )
+{
+ memset( cache, 0, sizeof( ssl_cache_context ) );
+
+ cache->timeout = SSL_CACHE_DEFAULT_TIMEOUT;
+ cache->max_entries = SSL_CACHE_DEFAULT_MAX_ENTRIES;
+}
+
+int ssl_cache_get( void *data, ssl_session *session )
+{
+ time_t t = time( NULL );
+ ssl_cache_context *cache = (ssl_cache_context *) data;
+ ssl_cache_entry *cur, *entry;
+
+ cur = cache->chain;
+ entry = NULL;
+
+ while( cur != NULL )
+ {
+ entry = cur;
+ cur = cur->next;
+
+ if( cache->timeout != 0 &&
+ (int) ( t - entry->timestamp ) > cache->timeout )
+ continue;
+
+ if( session->ciphersuite != entry->session.ciphersuite ||
+ session->compression != entry->session.compression ||
+ session->length != entry->session.length )
+ continue;
+
+ if( memcmp( session->id, entry->session.id,
+ entry->session.length ) != 0 )
+ continue;
+
+ memcpy( session->master, entry->session.master, 48 );
+
+ /*
+ * Restore peer certificate (without rest of the original chain)
+ */
+ if( entry->peer_cert.p != NULL )
+ {
+ session->peer_cert = (x509_cert *) malloc( sizeof(x509_cert) );
+ if( session->peer_cert == NULL )
+ return( 1 );
+
+ memset( session->peer_cert, 0, sizeof(x509_cert) );
+ if( x509parse_crt( session->peer_cert, entry->peer_cert.p,
+ entry->peer_cert.len ) != 0 )
+ {
+ free( session->peer_cert );
+ session->peer_cert = NULL;
+ return( 1 );
+ }
+ }
+
+ return( 0 );
+ }
+
+ return( 1 );
+}
+
+int ssl_cache_set( void *data, const ssl_session *session )
+{
+ time_t t = time( NULL ), oldest = 0;
+ ssl_cache_context *cache = (ssl_cache_context *) data;
+ ssl_cache_entry *cur, *prv, *old = NULL;
+ int count = 0;
+
+ cur = cache->chain;
+ prv = NULL;
+
+ while( cur != NULL )
+ {
+ count++;
+
+ if( cache->timeout != 0 &&
+ (int) ( t - cur->timestamp ) > cache->timeout )
+ {
+ cur->timestamp = t;
+ break; /* expired, reuse this slot, update timestamp */
+ }
+
+ if( memcmp( session->id, cur->session.id, cur->session.length ) == 0 )
+ break; /* client reconnected, keep timestamp for session id */
+
+ if( oldest == 0 || cur->timestamp < oldest )
+ {
+ oldest = cur->timestamp;
+ old = cur;
+ }
+
+ prv = cur;
+ cur = cur->next;
+ }
+
+ if( cur == NULL )
+ {
+ /*
+ * Reuse oldest entry if max_entries reached
+ */
+ if( old != NULL && count >= cache->max_entries )
+ {
+ cur = old;
+ memset( &cur->session, 0, sizeof(ssl_session) );
+ if( cur->peer_cert.p != NULL )
+ {
+ free( cur->peer_cert.p );
+ memset( &cur->peer_cert, 0, sizeof(x509_buf) );
+ }
+ }
+ else
+ {
+ cur = (ssl_cache_entry *) malloc( sizeof(ssl_cache_entry) );
+ if( cur == NULL )
+ return( 1 );
+
+ memset( cur, 0, sizeof(ssl_cache_entry) );
+
+ if( prv == NULL )
+ cache->chain = cur;
+ else
+ prv->next = cur;
+ }
+
+ cur->timestamp = t;
+ }
+
+ memcpy( &cur->session, session, sizeof( ssl_session ) );
+
+ /*
+ * Store peer certificate
+ */
+ if( session->peer_cert != NULL )
+ {
+ cur->peer_cert.p = (unsigned char *) malloc( session->peer_cert->raw.len );
+ if( cur->peer_cert.p == NULL )
+ return( 1 );
+
+ memcpy( cur->peer_cert.p, session->peer_cert->raw.p,
+ session->peer_cert->raw.len );
+ cur->peer_cert.len = session->peer_cert->raw.len;
+
+ cur->session.peer_cert = NULL;
+ }
+
+ return( 0 );
+}
+
+void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout )
+{
+ if( timeout < 0 ) timeout = 0;
+
+ cache->timeout = timeout;
+}
+
+void ssl_cache_set_max_entries( ssl_cache_context *cache, int max )
+{
+ if( max < 0 ) max = 0;
+
+ cache->max_entries = max;
+}
+
+void ssl_cache_free( ssl_cache_context *cache )
+{
+ ssl_cache_entry *cur, *prv;
+
+ cur = cache->chain;
+
+ while( cur != NULL )
+ {
+ prv = cur;
+ cur = cur->next;
+
+ ssl_session_free( &prv->session );
+
+ if( prv->peer_cert.p != NULL )
+ free( prv->peer_cert.p );
+
+ free( prv );
+ }
+}
+
+#endif /* POLARSSL_SSL_CACHE_C */
diff --git a/polarssl/ssl_cache.h b/polarssl/ssl_cache.h
new file mode 100644
index 0000000..521129a
--- /dev/null
+++ b/polarssl/ssl_cache.h
@@ -0,0 +1,119 @@
+/**
+ * \file ssl_cache.h
+ *
+ * \brief SSL session cache implementation
+ *
+ * Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SSL_CACHE_H
+#define POLARSSL_SSL_CACHE_H
+
+#include "polarssl/ssl.h"
+
+#if !defined(POLARSSL_CONFIG_OPTIONS)
+#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */
+#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */
+#endif /* !POLARSSL_CONFIG_OPTIONS */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _ssl_cache_context ssl_cache_context;
+typedef struct _ssl_cache_entry ssl_cache_entry;
+
+/**
+ * \brief This structure is used for storing cache entries
+ */
+struct _ssl_cache_entry
+{
+ time_t timestamp; /*!< entry timestamp */
+ ssl_session session; /*!< entry session */
+ x509_buf peer_cert; /*!< entry peer_cert */
+ ssl_cache_entry *next; /*!< chain pointer */
+};
+
+/**
+ * \brief Cache context
+ */
+struct _ssl_cache_context
+{
+ ssl_cache_entry *chain; /*!< start of the chain */
+ int timeout; /*!< cache entry timeout */
+ int max_entries; /*!< maximum entries */
+};
+
+/**
+ * \brief Initialize an SSL cache context
+ *
+ * \param cache SSL cache context
+ */
+void ssl_cache_init( ssl_cache_context *cache );
+
+/**
+ * \brief Cache get callback implementation
+ *
+ * \param data SSL cache context
+ * \param session session to retrieve entry for
+ */
+int ssl_cache_get( void *data, ssl_session *session );
+
+/**
+ * \brief Cache set callback implementation
+ *
+ * \param data SSL cache context
+ * \param session session to store entry for
+ */
+int ssl_cache_set( void *data, const ssl_session *session );
+
+/**
+ * \brief Set the cache timeout
+ * (Default: SSL_CACHE_DEFAULT_TIMEOUT (1 day))
+ *
+ * A timeout of 0 indicates no timeout.
+ *
+ * \param cache SSL cache context
+ * \param timeout cache entry timeout
+ */
+void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout );
+
+/**
+ * \brief Set the cache timeout
+ * (Default: SSL_CACHE_DEFAULT_MAX_ENTRIES (50))
+ *
+ * \param cache SSL cache context
+ * \param max cache entry maximum
+ */
+void ssl_cache_set_max_entries( ssl_cache_context *cache, int max );
+
+/**
+ * \brief Free referenced items in a cache context and clear memory
+ *
+ * \param cache SSL cache context
+ */
+void ssl_cache_free( ssl_cache_context *cache );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ssl_cache.h */
diff --git a/polarssl/ssl_cli.c b/polarssl/ssl_cli.c
new file mode 100644
index 0000000..e4a102b
--- /dev/null
+++ b/polarssl/ssl_cli.c
@@ -0,0 +1,1386 @@
+/*
+ * SSLv3/TLSv1 client-side functions
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SSL_CLI_C)
+
+#include "polarssl/debug.h"
+#include "polarssl/ssl.h"
+
+#include
+#include
+#include
+
+#if defined(POLARSSL_SHA4_C)
+#include "polarssl/sha4.h"
+#endif
+
+static int ssl_write_client_hello( ssl_context *ssl )
+{
+ int ret;
+ size_t i, n, ext_len = 0;
+ unsigned char *buf;
+ unsigned char *p;
+ time_t t;
+ unsigned char sig_alg_list[20];
+ size_t sig_alg_len = 0;
+
+ SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
+
+ if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+ {
+ ssl->major_ver = ssl->min_major_ver;
+ ssl->minor_ver = ssl->min_minor_ver;
+ }
+
+ if( ssl->max_major_ver == 0 && ssl->max_minor_ver == 0 )
+ {
+ ssl->max_major_ver = SSL_MAJOR_VERSION_3;
+ ssl->max_minor_ver = SSL_MINOR_VERSION_3;
+ }
+
+ /*
+ * 0 . 0 handshake type
+ * 1 . 3 handshake length
+ * 4 . 5 highest version supported
+ * 6 . 9 current UNIX time
+ * 10 . 37 random bytes
+ */
+ buf = ssl->out_msg;
+ p = buf + 4;
+
+ *p++ = (unsigned char) ssl->max_major_ver;
+ *p++ = (unsigned char) ssl->max_minor_ver;
+
+ SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]",
+ buf[4], buf[5] ) );
+
+ t = time( NULL );
+ *p++ = (unsigned char)( t >> 24 );
+ *p++ = (unsigned char)( t >> 16 );
+ *p++ = (unsigned char)( t >> 8 );
+ *p++ = (unsigned char)( t );
+
+ SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) );
+
+ if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 )
+ return( ret );
+
+ p += 28;
+
+ memcpy( ssl->handshake->randbytes, buf + 6, 32 );
+
+ SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 6, 32 );
+
+ /*
+ * 38 . 38 session id length
+ * 39 . 39+n session id
+ * 40+n . 41+n ciphersuitelist length
+ * 42+n . .. ciphersuitelist
+ * .. . .. compression methods length
+ * .. . .. compression methods
+ * .. . .. extensions length
+ * .. . .. extensions
+ */
+ n = ssl->session_negotiate->length;
+
+ if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE || n < 16 || n > 32 ||
+ ssl->handshake->resume == 0 )
+ n = 0;
+
+ *p++ = (unsigned char) n;
+
+ for( i = 0; i < n; i++ )
+ *p++ = ssl->session_negotiate->id[i];
+
+ SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) );
+ SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n );
+
+ for( n = 0; ssl->ciphersuites[ssl->minor_ver][n] != 0; n++ );
+ if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) n++;
+ *p++ = (unsigned char)( n >> 7 );
+ *p++ = (unsigned char)( n << 1 );
+
+ /*
+ * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+ */
+ if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+ {
+ *p++ = (unsigned char)( SSL_EMPTY_RENEGOTIATION_INFO >> 8 );
+ *p++ = (unsigned char)( SSL_EMPTY_RENEGOTIATION_INFO );
+ n--;
+ }
+
+ SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) );
+
+ for( i = 0; i < n; i++ )
+ {
+ SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %2d",
+ ssl->ciphersuites[ssl->minor_ver][i] ) );
+
+ *p++ = (unsigned char)( ssl->ciphersuites[ssl->minor_ver][i] >> 8 );
+ *p++ = (unsigned char)( ssl->ciphersuites[ssl->minor_ver][i] );
+ }
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+ SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) );
+ SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d",
+ SSL_COMPRESS_DEFLATE, SSL_COMPRESS_NULL ) );
+
+ *p++ = 2;
+ *p++ = SSL_COMPRESS_DEFLATE;
+ *p++ = SSL_COMPRESS_NULL;
+#else
+ SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) );
+ SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", SSL_COMPRESS_NULL ) );
+
+ *p++ = 1;
+ *p++ = SSL_COMPRESS_NULL;
+#endif
+
+ if ( ssl->hostname != NULL )
+ {
+ SSL_DEBUG_MSG( 3, ( "client hello, prepping for server name extension: %s",
+ ssl->hostname ) );
+
+ ext_len += ssl->hostname_len + 9;
+ }
+
+ if( ssl->renegotiation == SSL_RENEGOTIATION )
+ {
+ SSL_DEBUG_MSG( 3, ( "client hello, prepping for renegotiation extension" ) );
+ ext_len += 5 + ssl->verify_data_len;
+ }
+
+ /*
+ * Prepare signature_algorithms extension (TLS 1.2)
+ */
+ if( ssl->max_minor_ver == SSL_MINOR_VERSION_3 )
+ {
+#if defined(POLARSSL_SHA4_C)
+ sig_alg_list[sig_alg_len++] = SSL_HASH_SHA512;
+ sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+ sig_alg_list[sig_alg_len++] = SSL_HASH_SHA384;
+ sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+#endif
+#if defined(POLARSSL_SHA2_C)
+ sig_alg_list[sig_alg_len++] = SSL_HASH_SHA256;
+ sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+ sig_alg_list[sig_alg_len++] = SSL_HASH_SHA224;
+ sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+#endif
+#if defined(POLARSSL_SHA1_C)
+ sig_alg_list[sig_alg_len++] = SSL_HASH_SHA1;
+ sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+#endif
+#if defined(POLARSSL_MD5_C)
+ sig_alg_list[sig_alg_len++] = SSL_HASH_MD5;
+ sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+#endif
+ ext_len += 6 + sig_alg_len;
+ }
+
+ SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d",
+ ext_len ) );
+
+ *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( ext_len ) & 0xFF );
+
+ if ( ssl->hostname != NULL )
+ {
+ /*
+ * struct {
+ * NameType name_type;
+ * select (name_type) {
+ * case host_name: HostName;
+ * } name;
+ * } ServerName;
+ *
+ * enum {
+ * host_name(0), (255)
+ * } NameType;
+ *
+ * opaque HostName<1..2^16-1>;
+ *
+ * struct {
+ * ServerName server_name_list<1..2^16-1>
+ * } ServerNameList;
+ */
+ SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s",
+ ssl->hostname ) );
+
+ *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME ) & 0xFF );
+
+ *p++ = (unsigned char)( ( (ssl->hostname_len + 5) >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( (ssl->hostname_len + 5) ) & 0xFF );
+
+ *p++ = (unsigned char)( ( (ssl->hostname_len + 3) >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( (ssl->hostname_len + 3) ) & 0xFF );
+
+ *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->hostname_len >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->hostname_len ) & 0xFF );
+
+ memcpy( p, ssl->hostname, ssl->hostname_len );
+ p += ssl->hostname_len;
+ }
+
+ if( ssl->renegotiation == SSL_RENEGOTIATION )
+ {
+ /*
+ * Secure renegotiation
+ */
+ SSL_DEBUG_MSG( 3, ( "client hello, renegotiation info extension" ) );
+
+ *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO ) & 0xFF );
+
+ *p++ = 0x00;
+ *p++ = ( ssl->verify_data_len + 1 ) & 0xFF;
+ *p++ = ssl->verify_data_len & 0xFF;
+
+ memcpy( p, ssl->own_verify_data, ssl->verify_data_len );
+ p += ssl->verify_data_len;
+ }
+
+ if( ssl->max_minor_ver == SSL_MINOR_VERSION_3 )
+ {
+ /*
+ * enum {
+ * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
+ * sha512(6), (255)
+ * } HashAlgorithm;
+ *
+ * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
+ * SignatureAlgorithm;
+ *
+ * struct {
+ * HashAlgorithm hash;
+ * SignatureAlgorithm signature;
+ * } SignatureAndHashAlgorithm;
+ *
+ * SignatureAndHashAlgorithm
+ * supported_signature_algorithms<2..2^16-2>;
+ */
+ SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) );
+
+ *p++ = (unsigned char)( ( TLS_EXT_SIG_ALG >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( TLS_EXT_SIG_ALG ) & 0xFF );
+
+ *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF );
+
+ *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF );
+
+ memcpy( p, sig_alg_list, sig_alg_len );
+
+ p += sig_alg_len;
+ }
+
+ ssl->out_msglen = p - buf;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_CLIENT_HELLO;
+
+ ssl->state++;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write client hello" ) );
+
+ return( 0 );
+}
+
+static int ssl_parse_renegotiation_info( ssl_context *ssl,
+ unsigned char *buf,
+ size_t len )
+{
+ int ret;
+
+ if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+ {
+ if( len != 1 || buf[0] != 0x0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "non-zero length renegotiated connection field" ) );
+
+ if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
+ }
+ else
+ {
+ if( len != 1 + ssl->verify_data_len * 2 ||
+ buf[0] != ssl->verify_data_len * 2 ||
+ memcmp( buf + 1, ssl->own_verify_data, ssl->verify_data_len ) != 0 ||
+ memcmp( buf + 1 + ssl->verify_data_len,
+ ssl->peer_verify_data, ssl->verify_data_len ) != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "non-matching renegotiated connection field" ) );
+
+ if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+ }
+
+ return( 0 );
+}
+
+static int ssl_parse_server_hello( ssl_context *ssl )
+{
+#if defined(POLARSSL_DEBUG_C)
+ time_t t;
+#endif
+ int ret, i, comp;
+ size_t n;
+ size_t ext_len = 0;
+ unsigned char *buf, *ext;
+ int renegotiation_info_seen = 0;
+ int handshake_failure = 0;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) );
+
+ /*
+ * 0 . 0 handshake type
+ * 1 . 3 handshake length
+ * 4 . 5 protocol version
+ * 6 . 9 UNIX time()
+ * 10 . 37 random bytes
+ */
+ buf = ssl->in_msg;
+
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]",
+ buf[4], buf[5] ) );
+
+ if( ssl->in_hslen < 42 ||
+ buf[0] != SSL_HS_SERVER_HELLO ||
+ buf[4] != SSL_MAJOR_VERSION_3 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ if( buf[5] > ssl->max_minor_ver )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ ssl->minor_ver = buf[5];
+
+ if( ssl->minor_ver < ssl->min_minor_ver )
+ {
+ SSL_DEBUG_MSG( 1, ( "server only supports ssl smaller than minimum"
+ " [%d:%d] < [%d:%d]", ssl->major_ver, ssl->minor_ver,
+ buf[4], buf[5] ) );
+
+ ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
+ SSL_ALERT_MSG_PROTOCOL_VERSION );
+
+ return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
+ }
+
+#if defined(POLARSSL_DEBUG_C)
+ t = ( (time_t) buf[6] << 24 )
+ | ( (time_t) buf[7] << 16 )
+ | ( (time_t) buf[8] << 8 )
+ | ( (time_t) buf[9] );
+#endif
+
+ memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 );
+
+ n = buf[38];
+
+ SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
+ SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
+
+ if( n > 32 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ /*
+ * 38 . 38 session id length
+ * 39 . 38+n session id
+ * 39+n . 40+n chosen ciphersuite
+ * 41+n . 41+n chosen compression alg.
+ * 42+n . 43+n extensions length
+ * 44+n . 44+n+m extensions
+ */
+ if( ssl->in_hslen > 42 + n )
+ {
+ ext_len = ( ( buf[42 + n] << 8 )
+ | ( buf[43 + n] ) );
+
+ if( ( ext_len > 0 && ext_len < 4 ) ||
+ ssl->in_hslen != 44 + n + ext_len )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+ }
+
+ i = ( buf[39 + n] << 8 ) | buf[40 + n];
+ comp = buf[41 + n];
+
+ /*
+ * Initialize update checksum functions
+ */
+ ssl_optimize_checksum( ssl, i );
+
+ SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
+ SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n );
+
+ /*
+ * Check if the session can be resumed
+ */
+ if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE ||
+ ssl->handshake->resume == 0 || n == 0 ||
+ ssl->session_negotiate->ciphersuite != i ||
+ ssl->session_negotiate->compression != comp ||
+ ssl->session_negotiate->length != n ||
+ memcmp( ssl->session_negotiate->id, buf + 39, n ) != 0 )
+ {
+ ssl->state++;
+ ssl->handshake->resume = 0;
+ ssl->session_negotiate->start = time( NULL );
+ ssl->session_negotiate->ciphersuite = i;
+ ssl->session_negotiate->compression = comp;
+ ssl->session_negotiate->length = n;
+ memcpy( ssl->session_negotiate->id, buf + 39, n );
+ }
+ else
+ {
+ ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC;
+
+ if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+ return( ret );
+ }
+ }
+
+ SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
+ ssl->handshake->resume ? "a" : "no" ) );
+
+ SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d", i ) );
+ SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[41 + n] ) );
+
+ i = 0;
+ while( 1 )
+ {
+ if( ssl->ciphersuites[ssl->minor_ver][i] == 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ if( ssl->ciphersuites[ssl->minor_ver][i++] == ssl->session_negotiate->ciphersuite )
+ break;
+ }
+
+ if( comp != SSL_COMPRESS_NULL
+#if defined(POLARSSL_ZLIB_SUPPORT)
+ && comp != SSL_COMPRESS_DEFLATE
+#endif
+ )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+ ssl->session_negotiate->compression = comp;
+
+ ext = buf + 44 + n;
+
+ while( ext_len )
+ {
+ unsigned int ext_id = ( ( ext[0] << 8 )
+ | ( ext[1] ) );
+ unsigned int ext_size = ( ( ext[2] << 8 )
+ | ( ext[3] ) );
+
+ if( ext_size + 4 > ext_len )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ switch( ext_id )
+ {
+ case TLS_EXT_RENEGOTIATION_INFO:
+ SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) );
+ renegotiation_info_seen = 1;
+
+ if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ) ) != 0 )
+ return( ret );
+
+ break;
+
+ default:
+ SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
+ ext_id ) );
+ }
+
+ ext_len -= 4 + ext_size;
+ ext += 4 + ext_size;
+
+ if( ext_len > 0 && ext_len < 4 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+ }
+
+ /*
+ * Renegotiation security checks
+ */
+ if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+ ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
+ handshake_failure = 1;
+ }
+ else if( ssl->renegotiation == SSL_RENEGOTIATION &&
+ ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION &&
+ renegotiation_info_seen == 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) );
+ handshake_failure = 1;
+ }
+ else if( ssl->renegotiation == SSL_RENEGOTIATION &&
+ ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+ ssl->allow_legacy_renegotiation == SSL_LEGACY_NO_RENEGOTIATION )
+ {
+ SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
+ handshake_failure = 1;
+ }
+ else if( ssl->renegotiation == SSL_RENEGOTIATION &&
+ ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+ renegotiation_info_seen == 1 )
+ {
+ SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) );
+ handshake_failure = 1;
+ }
+
+ if( handshake_failure == 1 )
+ {
+ if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) );
+
+ return( 0 );
+}
+
+static int ssl_parse_server_key_exchange( ssl_context *ssl )
+{
+#if defined(POLARSSL_DHM_C)
+ int ret;
+ size_t n;
+ unsigned char *p, *end;
+ unsigned char hash[64];
+ md5_context md5;
+ sha1_context sha1;
+ int hash_id = SIG_RSA_RAW;
+ unsigned int hashlen = 0;
+#endif
+
+ SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );
+
+ if( ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_DES_CBC_SHA &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+ {
+ SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+#if !defined(POLARSSL_DHM_C)
+ SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) );
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+#else
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ if( ssl->in_msg[0] != SSL_HS_SERVER_KEY_EXCHANGE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+
+ SSL_DEBUG_BUF( 3, "server key exchange", ssl->in_msg + 4, ssl->in_hslen - 4 );
+
+ /*
+ * Ephemeral DH parameters:
+ *
+ * struct {
+ * opaque dh_p<1..2^16-1>;
+ * opaque dh_g<1..2^16-1>;
+ * opaque dh_Ys<1..2^16-1>;
+ * } ServerDHParams;
+ */
+ p = ssl->in_msg + 4;
+ end = ssl->in_msg + ssl->in_hslen;
+
+ if( ( ret = dhm_read_params( &ssl->handshake->dhm_ctx, &p, end ) ) != 0 )
+ {
+ SSL_DEBUG_MSG( 2, ( "DHM Read Params returned -0x%x", -ret ) );
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+ {
+ if( p[1] != SSL_SIG_RSA )
+ {
+ SSL_DEBUG_MSG( 2, ( "server used unsupported SignatureAlgorithm %d", p[1] ) );
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+
+ switch( p[0] )
+ {
+#if defined(POLARSSL_MD5_C)
+ case SSL_HASH_MD5:
+ hash_id = SIG_RSA_MD5;
+ break;
+#endif
+#if defined(POLARSSL_SHA1_C)
+ case SSL_HASH_SHA1:
+ hash_id = SIG_RSA_SHA1;
+ break;
+#endif
+#if defined(POLARSSL_SHA2_C)
+ case SSL_HASH_SHA224:
+ hash_id = SIG_RSA_SHA224;
+ break;
+ case SSL_HASH_SHA256:
+ hash_id = SIG_RSA_SHA256;
+ break;
+#endif
+#if defined(POLARSSL_SHA4_C)
+ case SSL_HASH_SHA384:
+ hash_id = SIG_RSA_SHA384;
+ break;
+ case SSL_HASH_SHA512:
+ hash_id = SIG_RSA_SHA512;
+ break;
+#endif
+ default:
+ SSL_DEBUG_MSG( 2, ( "Server used unsupported HashAlgorithm %d", p[0] ) );
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", p[1] ) );
+ SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", p[0] ) );
+ p += 2;
+ }
+
+ n = ( p[0] << 8 ) | p[1];
+ p += 2;
+
+ if( end != p + n )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+
+ if( (unsigned int)( end - p ) !=
+ ssl->session_negotiate->peer_cert->rsa.len )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+
+ if( ssl->handshake->dhm_ctx.len < 64 || ssl->handshake->dhm_ctx.len > 512 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+
+ SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P );
+ SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G );
+ SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY );
+
+ if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
+ {
+ /*
+ * digitally-signed struct {
+ * opaque md5_hash[16];
+ * opaque sha_hash[20];
+ * };
+ *
+ * md5_hash
+ * MD5(ClientHello.random + ServerHello.random
+ * + ServerParams);
+ * sha_hash
+ * SHA(ClientHello.random + ServerHello.random
+ * + ServerParams);
+ */
+ n = ssl->in_hslen - ( end - p ) - 6;
+
+ md5_starts( &md5 );
+ md5_update( &md5, ssl->handshake->randbytes, 64 );
+ md5_update( &md5, ssl->in_msg + 4, n );
+ md5_finish( &md5, hash );
+
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, ssl->handshake->randbytes, 64 );
+ sha1_update( &sha1, ssl->in_msg + 4, n );
+ sha1_finish( &sha1, hash + 16 );
+
+ hash_id = SIG_RSA_RAW;
+ hashlen = 36;
+ }
+ else
+ {
+ sha2_context sha2;
+#if defined(POLARSSL_SHA4_C)
+ sha4_context sha4;
+#endif
+
+ n = ssl->in_hslen - ( end - p ) - 8;
+
+ /*
+ * digitally-signed struct {
+ * opaque client_random[32];
+ * opaque server_random[32];
+ * ServerDHParams params;
+ * };
+ */
+ switch( hash_id )
+ {
+#if defined(POLARSSL_MD5_C)
+ case SIG_RSA_MD5:
+ md5_starts( &md5 );
+ md5_update( &md5, ssl->handshake->randbytes, 64 );
+ md5_update( &md5, ssl->in_msg + 4, n );
+ md5_finish( &md5, hash );
+ hashlen = 16;
+ break;
+#endif
+#if defined(POLARSSL_SHA1_C)
+ case SIG_RSA_SHA1:
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, ssl->handshake->randbytes, 64 );
+ sha1_update( &sha1, ssl->in_msg + 4, n );
+ sha1_finish( &sha1, hash );
+ hashlen = 20;
+ break;
+#endif
+#if defined(POLARSSL_SHA2_C)
+ case SIG_RSA_SHA224:
+ sha2_starts( &sha2, 1 );
+ sha2_update( &sha2, ssl->handshake->randbytes, 64 );
+ sha2_update( &sha2, ssl->in_msg + 4, n );
+ sha2_finish( &sha2, hash );
+ hashlen = 28;
+ break;
+ case SIG_RSA_SHA256:
+ sha2_starts( &sha2, 0 );
+ sha2_update( &sha2, ssl->handshake->randbytes, 64 );
+ sha2_update( &sha2, ssl->in_msg + 4, n );
+ sha2_finish( &sha2, hash );
+ hashlen = 32;
+ break;
+#endif
+#if defined(POLARSSL_SHA4_C)
+ case SIG_RSA_SHA384:
+ sha4_starts( &sha4, 1 );
+ sha4_update( &sha4, ssl->handshake->randbytes, 64 );
+ sha4_update( &sha4, ssl->in_msg + 4, n );
+ sha4_finish( &sha4, hash );
+ hashlen = 48;
+ break;
+ case SIG_RSA_SHA512:
+ sha4_starts( &sha4, 0 );
+ sha4_update( &sha4, ssl->handshake->randbytes, 64 );
+ sha4_update( &sha4, ssl->in_msg + 4, n );
+ sha4_finish( &sha4, hash );
+ hashlen = 64;
+ break;
+#endif
+ }
+ }
+
+ SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
+
+ if( ( ret = rsa_pkcs1_verify( &ssl->session_negotiate->peer_cert->rsa,
+ RSA_PUBLIC,
+ hash_id, hashlen, hash, p ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
+ return( ret );
+ }
+
+ ssl->state++;
+
+ SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) );
+
+ return( 0 );
+#endif
+}
+
+static int ssl_parse_certificate_request( ssl_context *ssl )
+{
+ int ret;
+ unsigned char *buf, *p;
+ size_t n = 0, m = 0;
+ size_t cert_type_len = 0, sig_alg_len = 0, dn_len = 0;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
+
+ /*
+ * 0 . 0 handshake type
+ * 1 . 3 handshake length
+ * 4 . 4 cert type count
+ * 5 .. m-1 cert types
+ * m .. m+1 sig alg length (TLS 1.2 only)
+ * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only)
+ * n .. n+1 length of all DNs
+ * n+2 .. n+3 length of DN 1
+ * n+4 .. ... Distinguished Name #1
+ * ... .. ... length of DN 2, etc.
+ */
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ ssl->client_auth = 0;
+ ssl->state++;
+
+ if( ssl->in_msg[0] == SSL_HS_CERTIFICATE_REQUEST )
+ ssl->client_auth++;
+
+ SSL_DEBUG_MSG( 3, ( "got %s certificate request",
+ ssl->client_auth ? "a" : "no" ) );
+
+ if( ssl->client_auth == 0 )
+ goto exit;
+
+ // TODO: handshake_failure alert for an anonymous server to request
+ // client authentication
+
+ buf = ssl->in_msg;
+
+ // Retrieve cert types
+ //
+ cert_type_len = buf[4];
+ n = cert_type_len;
+
+ if( ssl->in_hslen < 6 + n )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
+ }
+
+ p = buf + 5;
+ while( cert_type_len > 0 )
+ {
+ if( *p == SSL_CERT_TYPE_RSA_SIGN )
+ {
+ ssl->handshake->cert_type = SSL_CERT_TYPE_RSA_SIGN;
+ break;
+ }
+
+ cert_type_len--;
+ p++;
+ }
+
+ if( ssl->handshake->cert_type == 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "no known cert_type provided" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
+ }
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+ {
+ sig_alg_len = ( ( buf[5 + n] << 8 )
+ | ( buf[6 + n] ) );
+
+ p = buf + 7 + n;
+ m += 2;
+ n += sig_alg_len;
+
+ if( ssl->in_hslen < 6 + n )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
+ }
+ }
+
+ dn_len = ( ( buf[5 + m + n] << 8 )
+ | ( buf[6 + m + n] ) );
+
+ n += dn_len;
+ if( ssl->in_hslen != 7 + m + n )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
+ }
+
+exit:
+ SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) );
+
+ return( 0 );
+}
+
+static int ssl_parse_server_hello_done( ssl_context *ssl )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
+
+ if( ssl->client_auth != 0 )
+ {
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+ }
+
+ if( ssl->in_hslen != 4 ||
+ ssl->in_msg[0] != SSL_HS_SERVER_HELLO_DONE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE );
+ }
+
+ ssl->state++;
+
+ SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) );
+
+ return( 0 );
+}
+
+static int ssl_write_client_key_exchange( ssl_context *ssl )
+{
+ int ret;
+ size_t i, n;
+
+ SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) );
+
+ if( ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_DES_CBC_SHA ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+ {
+#if !defined(POLARSSL_DHM_C)
+ SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) );
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+#else
+ /*
+ * DHM key exchange -- send G^X mod P
+ */
+ n = ssl->handshake->dhm_ctx.len;
+
+ ssl->out_msg[4] = (unsigned char)( n >> 8 );
+ ssl->out_msg[5] = (unsigned char)( n );
+ i = 6;
+
+ ret = dhm_make_public( &ssl->handshake->dhm_ctx,
+ mpi_size( &ssl->handshake->dhm_ctx.P ),
+ &ssl->out_msg[i], n,
+ ssl->f_rng, ssl->p_rng );
+ if( ret != 0 )
+ {
+ SSL_DEBUG_RET( 1, "dhm_make_public", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X );
+ SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX );
+
+ ssl->handshake->pmslen = ssl->handshake->dhm_ctx.len;
+
+ if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
+ ssl->handshake->premaster,
+ &ssl->handshake->pmslen ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K );
+#endif
+ }
+ else
+ {
+ /*
+ * RSA key exchange -- send rsa_public(pkcs1 v1.5(premaster))
+ */
+ ssl->handshake->premaster[0] = (unsigned char) ssl->max_major_ver;
+ ssl->handshake->premaster[1] = (unsigned char) ssl->max_minor_ver;
+ ssl->handshake->pmslen = 48;
+
+ ret = ssl->f_rng( ssl->p_rng, ssl->handshake->premaster + 2,
+ ssl->handshake->pmslen - 2 );
+ if( ret != 0 )
+ return( ret );
+
+ i = 4;
+ n = ssl->session_negotiate->peer_cert->rsa.len;
+
+ if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
+ {
+ i += 2;
+ ssl->out_msg[4] = (unsigned char)( n >> 8 );
+ ssl->out_msg[5] = (unsigned char)( n );
+ }
+
+ ret = rsa_pkcs1_encrypt( &ssl->session_negotiate->peer_cert->rsa,
+ ssl->f_rng, ssl->p_rng,
+ RSA_PUBLIC,
+ ssl->handshake->pmslen,
+ ssl->handshake->premaster,
+ ssl->out_msg + i );
+ if( ret != 0 )
+ {
+ SSL_DEBUG_RET( 1, "rsa_pkcs1_encrypt", ret );
+ return( ret );
+ }
+ }
+
+ if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+ return( ret );
+ }
+
+ ssl->out_msglen = i + n;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_CLIENT_KEY_EXCHANGE;
+
+ ssl->state++;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) );
+
+ return( 0 );
+}
+
+static int ssl_write_certificate_verify( ssl_context *ssl )
+{
+ int ret = 0;
+ size_t n = 0, offset = 0;
+ unsigned char hash[48];
+ int hash_id = SIG_RSA_RAW;
+ unsigned int hashlen = 36;
+
+ SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
+
+ if( ssl->client_auth == 0 || ssl->own_cert == NULL )
+ {
+ SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+ if( ssl->rsa_key == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "got no private key" ) );
+ return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+ }
+
+ /*
+ * Make an RSA signature of the handshake digests
+ */
+ ssl->handshake->calc_verify( ssl, hash );
+
+ if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
+ {
+ /*
+ * digitally-signed struct {
+ * opaque md5_hash[16];
+ * opaque sha_hash[20];
+ * };
+ *
+ * md5_hash
+ * MD5(handshake_messages);
+ *
+ * sha_hash
+ * SHA(handshake_messages);
+ */
+ hashlen = 36;
+ hash_id = SIG_RSA_RAW;
+ }
+ else
+ {
+ /*
+ * digitally-signed struct {
+ * opaque handshake_messages[handshake_messages_length];
+ * };
+ *
+ * Taking shortcut here. We assume that the server always allows the
+ * PRF Hash function and has sent it in the allowed signature
+ * algorithms list received in the Certificate Request message.
+ *
+ * Until we encounter a server that does not, we will take this
+ * shortcut.
+ *
+ * Reason: Otherwise we should have running hashes for SHA512 and SHA224
+ * in order to satisfy 'weird' needs from the server side.
+ */
+ if( ssl->session_negotiate->ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+ {
+ hash_id = SIG_RSA_SHA384;
+ hashlen = 48;
+ ssl->out_msg[4] = SSL_HASH_SHA384;
+ ssl->out_msg[5] = SSL_SIG_RSA;
+ }
+ else
+ {
+ hash_id = SIG_RSA_SHA256;
+ hashlen = 32;
+ ssl->out_msg[4] = SSL_HASH_SHA256;
+ ssl->out_msg[5] = SSL_SIG_RSA;
+ }
+
+ offset = 2;
+ }
+
+ if ( ssl->rsa_key )
+ n = ssl->rsa_key_len ( ssl->rsa_key );
+
+ ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 );
+ ssl->out_msg[5 + offset] = (unsigned char)( n );
+
+ if( ssl->rsa_key )
+ {
+ ret = ssl->rsa_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng,
+ RSA_PRIVATE, hash_id,
+ hashlen, hash, ssl->out_msg + 6 + offset );
+ }
+
+ if (ret != 0)
+ {
+ SSL_DEBUG_RET( 1, "pkcs1_sign", ret );
+ return( ret );
+ }
+
+ ssl->out_msglen = 6 + n + offset;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_CERTIFICATE_VERIFY;
+
+ ssl->state++;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) );
+
+ return( 0 );
+}
+
+/*
+ * SSL handshake -- client side -- single step
+ */
+int ssl_handshake_client_step( ssl_context *ssl )
+{
+ int ret = 0;
+
+ if( ssl->state == SSL_HANDSHAKE_OVER )
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+ SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) );
+
+ if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+ return( ret );
+
+ switch( ssl->state )
+ {
+ case SSL_HELLO_REQUEST:
+ ssl->state = SSL_CLIENT_HELLO;
+ break;
+
+ /*
+ * ==> ClientHello
+ */
+ case SSL_CLIENT_HELLO:
+ ret = ssl_write_client_hello( ssl );
+ break;
+
+ /*
+ * <== ServerHello
+ * Certificate
+ * ( ServerKeyExchange )
+ * ( CertificateRequest )
+ * ServerHelloDone
+ */
+ case SSL_SERVER_HELLO:
+ ret = ssl_parse_server_hello( ssl );
+ break;
+
+ case SSL_SERVER_CERTIFICATE:
+ ret = ssl_parse_certificate( ssl );
+ break;
+
+ case SSL_SERVER_KEY_EXCHANGE:
+ ret = ssl_parse_server_key_exchange( ssl );
+ break;
+
+ case SSL_CERTIFICATE_REQUEST:
+ ret = ssl_parse_certificate_request( ssl );
+ break;
+
+ case SSL_SERVER_HELLO_DONE:
+ ret = ssl_parse_server_hello_done( ssl );
+ break;
+
+ /*
+ * ==> ( Certificate/Alert )
+ * ClientKeyExchange
+ * ( CertificateVerify )
+ * ChangeCipherSpec
+ * Finished
+ */
+ case SSL_CLIENT_CERTIFICATE:
+ ret = ssl_write_certificate( ssl );
+ break;
+
+ case SSL_CLIENT_KEY_EXCHANGE:
+ ret = ssl_write_client_key_exchange( ssl );
+ break;
+
+ case SSL_CERTIFICATE_VERIFY:
+ ret = ssl_write_certificate_verify( ssl );
+ break;
+
+ case SSL_CLIENT_CHANGE_CIPHER_SPEC:
+ ret = ssl_write_change_cipher_spec( ssl );
+ break;
+
+ case SSL_CLIENT_FINISHED:
+ ret = ssl_write_finished( ssl );
+ break;
+
+ /*
+ * <== ChangeCipherSpec
+ * Finished
+ */
+ case SSL_SERVER_CHANGE_CIPHER_SPEC:
+ ret = ssl_parse_change_cipher_spec( ssl );
+ break;
+
+ case SSL_SERVER_FINISHED:
+ ret = ssl_parse_finished( ssl );
+ break;
+
+ case SSL_FLUSH_BUFFERS:
+ SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
+ ssl->state = SSL_HANDSHAKE_WRAPUP;
+ break;
+
+ case SSL_HANDSHAKE_WRAPUP:
+ ssl_handshake_wrapup( ssl );
+ break;
+
+ default:
+ SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ return( ret );
+}
+#endif
diff --git a/polarssl/ssl_srv.c b/polarssl/ssl_srv.c
new file mode 100644
index 0000000..9ba2294
--- /dev/null
+++ b/polarssl/ssl_srv.c
@@ -0,0 +1,1623 @@
+/*
+ * SSLv3/TLSv1 server-side functions
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SSL_SRV_C)
+
+#include "polarssl/debug.h"
+#include "polarssl/ssl.h"
+
+#include
+#include
+#include
+
+static int ssl_parse_servername_ext( ssl_context *ssl,
+ const unsigned char *buf,
+ size_t len )
+{
+ int ret;
+ size_t servername_list_size, hostname_len;
+ const unsigned char *p;
+
+ servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
+ if( servername_list_size + 2 != len )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ p = buf + 2;
+ while( servername_list_size > 0 )
+ {
+ hostname_len = ( ( p[1] << 8 ) | p[2] );
+ if( hostname_len + 3 > servername_list_size )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ if( p[0] == TLS_EXT_SERVERNAME_HOSTNAME )
+ {
+ ret = ssl->f_sni( ssl->p_sni, ssl, p + 3, hostname_len );
+ if( ret != 0 )
+ {
+ ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
+ SSL_ALERT_MSG_UNRECOGNIZED_NAME );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+ return( 0 );
+ }
+
+ servername_list_size -= hostname_len + 3;
+ p += hostname_len + 3;
+ }
+
+ if( servername_list_size != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ return( 0 );
+}
+
+static int ssl_parse_renegotiation_info( ssl_context *ssl,
+ const unsigned char *buf,
+ size_t len )
+{
+ int ret;
+
+ if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
+ {
+ if( len != 1 || buf[0] != 0x0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "non-zero length renegotiated connection field" ) );
+
+ if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
+ }
+ else
+ {
+ if( len != 1 + ssl->verify_data_len ||
+ buf[0] != ssl->verify_data_len ||
+ memcmp( buf + 1, ssl->peer_verify_data, ssl->verify_data_len ) != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "non-matching renegotiated connection field" ) );
+
+ if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+ }
+
+ return( 0 );
+}
+
+static int ssl_parse_signature_algorithms_ext( ssl_context *ssl,
+ const unsigned char *buf,
+ size_t len )
+{
+ size_t sig_alg_list_size;
+ const unsigned char *p;
+
+ sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
+ if( sig_alg_list_size + 2 != len ||
+ sig_alg_list_size %2 != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ p = buf + 2;
+ while( sig_alg_list_size > 0 )
+ {
+ if( p[1] != SSL_SIG_RSA )
+ {
+ sig_alg_list_size -= 2;
+ p += 2;
+ continue;
+ }
+#if defined(POLARSSL_SHA4_C)
+ if( p[0] == SSL_HASH_SHA512 )
+ {
+ ssl->handshake->sig_alg = SSL_HASH_SHA512;
+ break;
+ }
+ if( p[0] == SSL_HASH_SHA384 )
+ {
+ ssl->handshake->sig_alg = SSL_HASH_SHA384;
+ break;
+ }
+#endif
+#if defined(POLARSSL_SHA2_C)
+ if( p[0] == SSL_HASH_SHA256 )
+ {
+ ssl->handshake->sig_alg = SSL_HASH_SHA256;
+ break;
+ }
+ if( p[0] == SSL_HASH_SHA224 )
+ {
+ ssl->handshake->sig_alg = SSL_HASH_SHA224;
+ break;
+ }
+#endif
+ if( p[0] == SSL_HASH_SHA1 )
+ {
+ ssl->handshake->sig_alg = SSL_HASH_SHA1;
+ break;
+ }
+ if( p[0] == SSL_HASH_MD5 )
+ {
+ ssl->handshake->sig_alg = SSL_HASH_MD5;
+ break;
+ }
+
+ sig_alg_list_size -= 2;
+ p += 2;
+ }
+
+ SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d",
+ ssl->handshake->sig_alg ) );
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
+static int ssl_parse_client_hello_v2( ssl_context *ssl )
+{
+ int ret;
+ unsigned int i, j;
+ size_t n;
+ unsigned int ciph_len, sess_len, chal_len;
+ unsigned char *buf, *p;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) );
+
+ if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) );
+
+ if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ buf = ssl->in_hdr;
+
+ SSL_DEBUG_BUF( 4, "record header", buf, 5 );
+
+ SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d",
+ buf[2] ) );
+ SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d",
+ ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) );
+ SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]",
+ buf[3], buf[4] ) );
+
+ /*
+ * SSLv2 Client Hello
+ *
+ * Record layer:
+ * 0 . 1 message length
+ *
+ * SSL layer:
+ * 2 . 2 message type
+ * 3 . 4 protocol version
+ */
+ if( buf[2] != SSL_HS_CLIENT_HELLO ||
+ buf[3] != SSL_MAJOR_VERSION_3 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF;
+
+ if( n < 17 || n > 512 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ ssl->major_ver = SSL_MAJOR_VERSION_3;
+ ssl->minor_ver = ( buf[4] <= SSL_MINOR_VERSION_3 )
+ ? buf[4] : SSL_MINOR_VERSION_3;
+
+ if( ssl->minor_ver < ssl->min_minor_ver )
+ {
+ SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum"
+ " [%d:%d] < [%d:%d]", ssl->major_ver, ssl->minor_ver,
+ ssl->min_major_ver, ssl->min_minor_ver ) );
+
+ ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
+ SSL_ALERT_MSG_PROTOCOL_VERSION );
+ return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
+ }
+
+ ssl->max_major_ver = buf[3];
+ ssl->max_minor_ver = buf[4];
+
+ if( ( ret = ssl_fetch_input( ssl, 2 + n ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+ return( ret );
+ }
+
+ ssl->handshake->update_checksum( ssl, buf + 2, n );
+
+ buf = ssl->in_msg;
+ n = ssl->in_left - 5;
+
+ /*
+ * 0 . 1 ciphersuitelist length
+ * 2 . 3 session id length
+ * 4 . 5 challenge length
+ * 6 . .. ciphersuitelist
+ * .. . .. session id
+ * .. . .. challenge
+ */
+ SSL_DEBUG_BUF( 4, "record contents", buf, n );
+
+ ciph_len = ( buf[0] << 8 ) | buf[1];
+ sess_len = ( buf[2] << 8 ) | buf[3];
+ chal_len = ( buf[4] << 8 ) | buf[5];
+
+ SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d",
+ ciph_len, sess_len, chal_len ) );
+
+ /*
+ * Make sure each parameter length is valid
+ */
+ if( ciph_len < 3 || ( ciph_len % 3 ) != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ if( sess_len > 32 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ if( chal_len < 8 || chal_len > 32 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ if( n != 6 + ciph_len + sess_len + chal_len )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
+ buf + 6, ciph_len );
+ SSL_DEBUG_BUF( 3, "client hello, session id",
+ buf + 6 + ciph_len, sess_len );
+ SSL_DEBUG_BUF( 3, "client hello, challenge",
+ buf + 6 + ciph_len + sess_len, chal_len );
+
+ p = buf + 6 + ciph_len;
+ ssl->session_negotiate->length = sess_len;
+ memset( ssl->session_negotiate->id, 0, sizeof( ssl->session_negotiate->id ) );
+ memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->length );
+
+ p += sess_len;
+ memset( ssl->handshake->randbytes, 0, 64 );
+ memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len );
+
+ /*
+ * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+ */
+ for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 )
+ {
+ if( p[0] == 0 && p[1] == 0 && p[2] == SSL_EMPTY_RENEGOTIATION_INFO )
+ {
+ SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) );
+ if( ssl->renegotiation == SSL_RENEGOTIATION )
+ {
+ SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) );
+
+ if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+ ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
+ break;
+ }
+ }
+
+ for( i = 0; ssl->ciphersuites[ssl->minor_ver][i] != 0; i++ )
+ {
+ for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
+ {
+ if( p[0] == 0 &&
+ p[1] == 0 &&
+ p[2] == ssl->ciphersuites[ssl->minor_ver][i] )
+ goto have_ciphersuite_v2;
+ }
+ }
+
+ SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
+
+ return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN );
+
+have_ciphersuite_v2:
+ ssl->session_negotiate->ciphersuite = ssl->ciphersuites[ssl->minor_ver][i];
+ ssl_optimize_checksum( ssl, ssl->session_negotiate->ciphersuite );
+
+ /*
+ * SSLv2 Client Hello relevant renegotiation security checks
+ */
+ if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+ ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
+
+ if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ ssl->in_left = 0;
+ ssl->state++;
+
+ SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) );
+
+ return( 0 );
+}
+#endif /* POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */
+
+static int ssl_parse_client_hello( ssl_context *ssl )
+{
+ int ret;
+ unsigned int i, j;
+ size_t n;
+ unsigned int ciph_len, sess_len;
+ unsigned int comp_len;
+ unsigned int ext_len = 0;
+ unsigned char *buf, *p, *ext;
+ int renegotiation_info_seen = 0;
+ int handshake_failure = 0;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
+
+ if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE &&
+ ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+ return( ret );
+ }
+
+ buf = ssl->in_hdr;
+
+#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
+ if( ( buf[0] & 0x80 ) != 0 )
+ return ssl_parse_client_hello_v2( ssl );
+#endif
+
+ SSL_DEBUG_BUF( 4, "record header", buf, 5 );
+
+ SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d",
+ buf[0] ) );
+ SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d",
+ ( buf[3] << 8 ) | buf[4] ) );
+ SSL_DEBUG_MSG( 3, ( "client hello v3, protocol ver: [%d:%d]",
+ buf[1], buf[2] ) );
+
+ /*
+ * SSLv3 Client Hello
+ *
+ * Record layer:
+ * 0 . 0 message type
+ * 1 . 2 protocol version
+ * 3 . 4 message length
+ */
+ if( buf[0] != SSL_MSG_HANDSHAKE ||
+ buf[1] != SSL_MAJOR_VERSION_3 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ n = ( buf[3] << 8 ) | buf[4];
+
+ if( n < 45 || n > 512 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE &&
+ ( ret = ssl_fetch_input( ssl, 5 + n ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+ return( ret );
+ }
+
+ buf = ssl->in_msg;
+ if( !ssl->renegotiation )
+ n = ssl->in_left - 5;
+ else
+ n = ssl->in_msglen;
+
+ ssl->handshake->update_checksum( ssl, buf, n );
+
+ /*
+ * SSL layer:
+ * 0 . 0 handshake type
+ * 1 . 3 handshake length
+ * 4 . 5 protocol version
+ * 6 . 9 UNIX time()
+ * 10 . 37 random bytes
+ * 38 . 38 session id length
+ * 39 . 38+x session id
+ * 39+x . 40+x ciphersuitelist length
+ * 41+x . .. ciphersuitelist
+ * .. . .. compression alg.
+ * .. . .. extensions
+ */
+ SSL_DEBUG_BUF( 4, "record contents", buf, n );
+
+ SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d",
+ buf[0] ) );
+ SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d",
+ ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) );
+ SSL_DEBUG_MSG( 3, ( "client hello v3, max. version: [%d:%d]",
+ buf[4], buf[5] ) );
+
+ /*
+ * Check the handshake type and protocol version
+ */
+ if( buf[0] != SSL_HS_CLIENT_HELLO ||
+ buf[4] != SSL_MAJOR_VERSION_3 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ ssl->major_ver = SSL_MAJOR_VERSION_3;
+ ssl->minor_ver = ( buf[5] <= SSL_MINOR_VERSION_3 )
+ ? buf[5] : SSL_MINOR_VERSION_3;
+
+ if( ssl->minor_ver < ssl->min_minor_ver )
+ {
+ SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum"
+ " [%d:%d] < [%d:%d]", ssl->major_ver, ssl->minor_ver,
+ ssl->min_major_ver, ssl->min_minor_ver ) );
+
+ ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
+ SSL_ALERT_MSG_PROTOCOL_VERSION );
+
+ return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
+ }
+
+ ssl->max_major_ver = buf[4];
+ ssl->max_minor_ver = buf[5];
+
+ memcpy( ssl->handshake->randbytes, buf + 6, 32 );
+
+ /*
+ * Check the handshake message length
+ */
+ if( buf[1] != 0 || n != (unsigned int) 4 + ( ( buf[2] << 8 ) | buf[3] ) )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ /*
+ * Check the session length
+ */
+ sess_len = buf[38];
+
+ if( sess_len > 32 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ ssl->session_negotiate->length = sess_len;
+ memset( ssl->session_negotiate->id, 0,
+ sizeof( ssl->session_negotiate->id ) );
+ memcpy( ssl->session_negotiate->id, buf + 39,
+ ssl->session_negotiate->length );
+
+ /*
+ * Check the ciphersuitelist length
+ */
+ ciph_len = ( buf[39 + sess_len] << 8 )
+ | ( buf[40 + sess_len] );
+
+ if( ciph_len < 2 || ciph_len > 256 || ( ciph_len % 2 ) != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ /*
+ * Check the compression algorithms length
+ */
+ comp_len = buf[41 + sess_len + ciph_len];
+
+ if( comp_len < 1 || comp_len > 16 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ /*
+ * Check the extension length
+ */
+ if( n > 42 + sess_len + ciph_len + comp_len )
+ {
+ ext_len = ( buf[42 + sess_len + ciph_len + comp_len] << 8 )
+ | ( buf[43 + sess_len + ciph_len + comp_len] );
+
+ if( ( ext_len > 0 && ext_len < 4 ) ||
+ n != 44 + sess_len + ciph_len + comp_len + ext_len )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ SSL_DEBUG_BUF( 3, "Ext", buf + 44 + sess_len + ciph_len + comp_len, ext_len);
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+ }
+
+ ssl->session_negotiate->compression = SSL_COMPRESS_NULL;
+#if defined(POLARSSL_ZLIB_SUPPORT)
+ for( i = 0; i < comp_len; ++i )
+ {
+ if( buf[42 + sess_len + ciph_len + i] == SSL_COMPRESS_DEFLATE )
+ {
+ ssl->session_negotiate->compression = SSL_COMPRESS_DEFLATE;
+ break;
+ }
+ }
+#endif
+
+ SSL_DEBUG_BUF( 3, "client hello, random bytes",
+ buf + 6, 32 );
+ SSL_DEBUG_BUF( 3, "client hello, session id",
+ buf + 38, sess_len );
+ SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
+ buf + 41 + sess_len, ciph_len );
+ SSL_DEBUG_BUF( 3, "client hello, compression",
+ buf + 42 + sess_len + ciph_len, comp_len );
+
+ /*
+ * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+ */
+ for( i = 0, p = buf + 41 + sess_len; i < ciph_len; i += 2, p += 2 )
+ {
+ if( p[0] == 0 && p[1] == SSL_EMPTY_RENEGOTIATION_INFO )
+ {
+ SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) );
+ if( ssl->renegotiation == SSL_RENEGOTIATION )
+ {
+ SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) );
+
+ if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+ ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
+ break;
+ }
+ }
+
+ /*
+ * Search for a matching ciphersuite
+ */
+ for( i = 0; ssl->ciphersuites[ssl->minor_ver][i] != 0; i++ )
+ {
+ for( j = 0, p = buf + 41 + sess_len; j < ciph_len;
+ j += 2, p += 2 )
+ {
+ if( p[0] == 0 && p[1] == ssl->ciphersuites[ssl->minor_ver][i] )
+ goto have_ciphersuite;
+ }
+ }
+
+ SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
+
+ return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN );
+
+have_ciphersuite:
+ ssl->session_negotiate->ciphersuite = ssl->ciphersuites[ssl->minor_ver][i];
+ ssl_optimize_checksum( ssl, ssl->session_negotiate->ciphersuite );
+
+ ext = buf + 44 + sess_len + ciph_len + comp_len;
+
+ while( ext_len )
+ {
+ unsigned int ext_id = ( ( ext[0] << 8 )
+ | ( ext[1] ) );
+ unsigned int ext_size = ( ( ext[2] << 8 )
+ | ( ext[3] ) );
+
+ if( ext_size + 4 > ext_len )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+ switch( ext_id )
+ {
+ case TLS_EXT_SERVERNAME:
+ SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) );
+ if( ssl->f_sni == NULL )
+ break;
+
+ ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size );
+ if( ret != 0 )
+ return( ret );
+ break;
+
+ case TLS_EXT_RENEGOTIATION_INFO:
+ SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) );
+ renegotiation_info_seen = 1;
+
+ ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size );
+ if( ret != 0 )
+ return( ret );
+ break;
+
+ case TLS_EXT_SIG_ALG:
+ SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
+ if( ssl->renegotiation == SSL_RENEGOTIATION )
+ break;
+
+ ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size );
+ if( ret != 0 )
+ return( ret );
+ break;
+
+ default:
+ SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
+ ext_id ) );
+ }
+
+ ext_len -= 4 + ext_size;
+ ext += 4 + ext_size;
+
+ if( ext_len > 0 && ext_len < 4 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+ }
+
+ /*
+ * Renegotiation security checks
+ */
+ if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+ ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
+ handshake_failure = 1;
+ }
+ else if( ssl->renegotiation == SSL_RENEGOTIATION &&
+ ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION &&
+ renegotiation_info_seen == 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) );
+ handshake_failure = 1;
+ }
+ else if( ssl->renegotiation == SSL_RENEGOTIATION &&
+ ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+ ssl->allow_legacy_renegotiation == SSL_LEGACY_NO_RENEGOTIATION )
+ {
+ SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
+ handshake_failure = 1;
+ }
+ else if( ssl->renegotiation == SSL_RENEGOTIATION &&
+ ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+ renegotiation_info_seen == 1 )
+ {
+ SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) );
+ handshake_failure = 1;
+ }
+
+ if( handshake_failure == 1 )
+ {
+ if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ ssl->in_left = 0;
+ ssl->state++;
+
+ SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) );
+
+ return( 0 );
+}
+
+static int ssl_write_server_hello( ssl_context *ssl )
+{
+ time_t t;
+ int ret, n;
+ size_t ext_len = 0;
+ unsigned char *buf, *p;
+
+ SSL_DEBUG_MSG( 2, ( "=> write server hello" ) );
+
+ /*
+ * 0 . 0 handshake type
+ * 1 . 3 handshake length
+ * 4 . 5 protocol version
+ * 6 . 9 UNIX time()
+ * 10 . 37 random bytes
+ */
+ buf = ssl->out_msg;
+ p = buf + 4;
+
+ *p++ = (unsigned char) ssl->major_ver;
+ *p++ = (unsigned char) ssl->minor_ver;
+
+ SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]",
+ buf[4], buf[5] ) );
+
+ t = time( NULL );
+ *p++ = (unsigned char)( t >> 24 );
+ *p++ = (unsigned char)( t >> 16 );
+ *p++ = (unsigned char)( t >> 8 );
+ *p++ = (unsigned char)( t );
+
+ SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
+
+ if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 )
+ return( ret );
+
+ p += 28;
+
+ memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 );
+
+ SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
+
+ /*
+ * 38 . 38 session id length
+ * 39 . 38+n session id
+ * 39+n . 40+n chosen ciphersuite
+ * 41+n . 41+n chosen compression alg.
+ */
+ ssl->session_negotiate->length = n = 32;
+ *p++ = (unsigned char) ssl->session_negotiate->length;
+
+ if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE ||
+ ssl->f_get_cache == NULL ||
+ ssl->f_get_cache( ssl->p_get_cache, ssl->session_negotiate ) != 0 )
+ {
+ /*
+ * Not found, create a new session id
+ */
+ ssl->handshake->resume = 0;
+ ssl->state++;
+
+ if( ( ret = ssl->f_rng( ssl->p_rng, ssl->session_negotiate->id,
+ n ) ) != 0 )
+ return( ret );
+ }
+ else
+ {
+ /*
+ * Found a matching session, resuming it
+ */
+ ssl->handshake->resume = 1;
+ ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC;
+
+ if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+ return( ret );
+ }
+ }
+
+ memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->length );
+ p += ssl->session_negotiate->length;
+
+ SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
+ SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n );
+ SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
+ ssl->handshake->resume ? "a" : "no" ) );
+
+ *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 );
+ *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite );
+ *p++ = (unsigned char)( ssl->session_negotiate->compression );
+
+ SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d",
+ ssl->session_negotiate->ciphersuite ) );
+ SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d",
+ ssl->session_negotiate->compression ) );
+
+ if( ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION )
+ {
+ SSL_DEBUG_MSG( 3, ( "server hello, prepping for secure renegotiation extension" ) );
+ ext_len += 5 + ssl->verify_data_len * 2;
+
+ SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d",
+ ext_len ) );
+
+ *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( ext_len ) & 0xFF );
+
+ /*
+ * Secure renegotiation
+ */
+ SSL_DEBUG_MSG( 3, ( "client hello, secure renegotiation extension" ) );
+
+ *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO ) & 0xFF );
+
+ *p++ = 0x00;
+ *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF;
+ *p++ = ssl->verify_data_len * 2 & 0xFF;
+
+ memcpy( p, ssl->peer_verify_data, ssl->verify_data_len );
+ p += ssl->verify_data_len;
+ memcpy( p, ssl->own_verify_data, ssl->verify_data_len );
+ p += ssl->verify_data_len;
+ }
+
+ ssl->out_msglen = p - buf;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_SERVER_HELLO;
+
+ ret = ssl_write_record( ssl );
+
+ SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
+
+ return( ret );
+}
+
+static int ssl_write_certificate_request( ssl_context *ssl )
+{
+ int ret;
+ size_t n = 0, dn_size, total_dn_size;
+ unsigned char *buf, *p;
+ const x509_cert *crt;
+
+ SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
+
+ ssl->state++;
+
+ if( ssl->authmode == SSL_VERIFY_NONE )
+ {
+ SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
+ return( 0 );
+ }
+
+ /*
+ * 0 . 0 handshake type
+ * 1 . 3 handshake length
+ * 4 . 4 cert type count
+ * 5 .. m-1 cert types
+ * m .. m+1 sig alg length (TLS 1.2 only)
+ * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only)
+ * n .. n+1 length of all DNs
+ * n+2 .. n+3 length of DN 1
+ * n+4 .. ... Distinguished Name #1
+ * ... .. ... length of DN 2, etc.
+ */
+ buf = ssl->out_msg;
+ p = buf + 4;
+
+ /*
+ * At the moment, only RSA certificates are supported
+ */
+ *p++ = 1;
+ *p++ = SSL_CERT_TYPE_RSA_SIGN;
+
+ /*
+ * Add signature_algorithms for verify (TLS 1.2)
+ * Only add current running algorithm that is already required for
+ * requested ciphersuite.
+ *
+ * Length is always 2
+ */
+ if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+ {
+ ssl->handshake->verify_sig_alg = SSL_HASH_SHA256;
+
+ *p++ = 0;
+ *p++ = 2;
+
+ if( ssl->session_negotiate->ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+ {
+ ssl->handshake->verify_sig_alg = SSL_HASH_SHA384;
+ }
+
+ *p++ = ssl->handshake->verify_sig_alg;
+ *p++ = SSL_SIG_RSA;
+
+ n += 4;
+ }
+
+ p += 2;
+ crt = ssl->ca_chain;
+
+ total_dn_size = 0;
+ while( crt != NULL && crt->version != 0)
+ {
+ if( p - buf > 4096 )
+ break;
+
+ dn_size = crt->subject_raw.len;
+ *p++ = (unsigned char)( dn_size >> 8 );
+ *p++ = (unsigned char)( dn_size );
+ memcpy( p, crt->subject_raw.p, dn_size );
+ p += dn_size;
+
+ SSL_DEBUG_BUF( 3, "requested DN", p, dn_size );
+
+ total_dn_size += 2 + dn_size;
+ crt = crt->next;
+ }
+
+ ssl->out_msglen = p - buf;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_CERTIFICATE_REQUEST;
+ ssl->out_msg[6 + n] = (unsigned char)( total_dn_size >> 8 );
+ ssl->out_msg[7 + n] = (unsigned char)( total_dn_size );
+
+ ret = ssl_write_record( ssl );
+
+ SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) );
+
+ return( ret );
+}
+
+static int ssl_write_server_key_exchange( ssl_context *ssl )
+{
+#if defined(POLARSSL_DHM_C)
+ int ret;
+ size_t n, rsa_key_len = 0;
+ unsigned char hash[64];
+ int hash_id = 0;
+ unsigned int hashlen = 0;
+#endif
+
+ SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
+
+ if( ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_DES_CBC_SHA &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 &&
+ ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+ {
+ SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+#if !defined(POLARSSL_DHM_C)
+ SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) );
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+#else
+
+ if( ssl->rsa_key == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "got no private key" ) );
+ return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+ }
+
+ /*
+ * Ephemeral DH parameters:
+ *
+ * struct {
+ * opaque dh_p<1..2^16-1>;
+ * opaque dh_g<1..2^16-1>;
+ * opaque dh_Ys<1..2^16-1>;
+ * } ServerDHParams;
+ */
+ if( ( ret = mpi_copy( &ssl->handshake->dhm_ctx.P, &ssl->dhm_P ) ) != 0 ||
+ ( ret = mpi_copy( &ssl->handshake->dhm_ctx.G, &ssl->dhm_G ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "mpi_copy", ret );
+ return( ret );
+ }
+
+ if( ( ret = dhm_make_params( &ssl->handshake->dhm_ctx,
+ mpi_size( &ssl->handshake->dhm_ctx.P ),
+ ssl->out_msg + 4,
+ &n, ssl->f_rng, ssl->p_rng ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "dhm_make_params", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X );
+ SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P );
+ SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G );
+ SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX );
+
+ if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
+ {
+ md5_context md5;
+ sha1_context sha1;
+
+ /*
+ * digitally-signed struct {
+ * opaque md5_hash[16];
+ * opaque sha_hash[20];
+ * };
+ *
+ * md5_hash
+ * MD5(ClientHello.random + ServerHello.random
+ * + ServerParams);
+ * sha_hash
+ * SHA(ClientHello.random + ServerHello.random
+ * + ServerParams);
+ */
+ md5_starts( &md5 );
+ md5_update( &md5, ssl->handshake->randbytes, 64 );
+ md5_update( &md5, ssl->out_msg + 4, n );
+ md5_finish( &md5, hash );
+
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, ssl->handshake->randbytes, 64 );
+ sha1_update( &sha1, ssl->out_msg + 4, n );
+ sha1_finish( &sha1, hash + 16 );
+
+ hashlen = 36;
+ hash_id = SIG_RSA_RAW;
+ }
+ else
+ {
+ /*
+ * digitally-signed struct {
+ * opaque client_random[32];
+ * opaque server_random[32];
+ * ServerDHParams params;
+ * };
+ */
+#if defined(POLARSSL_SHA4_C)
+ if( ssl->handshake->sig_alg == SSL_HASH_SHA512 )
+ {
+ sha4_context sha4;
+
+ sha4_starts( &sha4, 0 );
+ sha4_update( &sha4, ssl->handshake->randbytes, 64 );
+ sha4_update( &sha4, ssl->out_msg + 4, n );
+ sha4_finish( &sha4, hash );
+
+ hashlen = 64;
+ hash_id = SIG_RSA_SHA512;
+ }
+ else if( ssl->handshake->sig_alg == SSL_HASH_SHA384 )
+ {
+ sha4_context sha4;
+
+ sha4_starts( &sha4, 1 );
+ sha4_update( &sha4, ssl->handshake->randbytes, 64 );
+ sha4_update( &sha4, ssl->out_msg + 4, n );
+ sha4_finish( &sha4, hash );
+
+ hashlen = 48;
+ hash_id = SIG_RSA_SHA384;
+ }
+ else
+#endif
+#if defined(POLARSSL_SHA2_C)
+ if( ssl->handshake->sig_alg == SSL_HASH_SHA256 )
+ {
+ sha2_context sha2;
+
+ sha2_starts( &sha2, 0 );
+ sha2_update( &sha2, ssl->handshake->randbytes, 64 );
+ sha2_update( &sha2, ssl->out_msg + 4, n );
+ sha2_finish( &sha2, hash );
+
+ hashlen = 32;
+ hash_id = SIG_RSA_SHA256;
+ }
+ else if( ssl->handshake->sig_alg == SSL_HASH_SHA224 )
+ {
+ sha2_context sha2;
+
+ sha2_starts( &sha2, 1 );
+ sha2_update( &sha2, ssl->handshake->randbytes, 64 );
+ sha2_update( &sha2, ssl->out_msg + 4, n );
+ sha2_finish( &sha2, hash );
+
+ hashlen = 24;
+ hash_id = SIG_RSA_SHA224;
+ }
+ else
+#endif
+ if( ssl->handshake->sig_alg == SSL_HASH_SHA1 )
+ {
+ sha1_context sha1;
+
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, ssl->handshake->randbytes, 64 );
+ sha1_update( &sha1, ssl->out_msg + 4, n );
+ sha1_finish( &sha1, hash );
+
+ hashlen = 20;
+ hash_id = SIG_RSA_SHA1;
+ }
+ else if( ssl->handshake->sig_alg == SSL_HASH_MD5 )
+ {
+ md5_context md5;
+
+ md5_starts( &md5 );
+ md5_update( &md5, ssl->handshake->randbytes, 64 );
+ md5_update( &md5, ssl->out_msg + 4, n );
+ md5_finish( &md5, hash );
+
+ hashlen = 16;
+ hash_id = SIG_RSA_MD5;
+ }
+ }
+
+ SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
+
+ if ( ssl->rsa_key )
+ rsa_key_len = ssl->rsa_key_len( ssl->rsa_key );
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+ {
+ ssl->out_msg[4 + n] = ssl->handshake->sig_alg;
+ ssl->out_msg[5 + n] = SSL_SIG_RSA;
+
+ n += 2;
+ }
+
+ ssl->out_msg[4 + n] = (unsigned char)( rsa_key_len >> 8 );
+ ssl->out_msg[5 + n] = (unsigned char)( rsa_key_len );
+
+ if ( ssl->rsa_key )
+ {
+ ret = ssl->rsa_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng,
+ RSA_PRIVATE,
+ hash_id, hashlen, hash,
+ ssl->out_msg + 6 + n );
+ }
+
+ if( ret != 0 )
+ {
+ SSL_DEBUG_RET( 1, "pkcs1_sign", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_BUF( 3, "my RSA sig", ssl->out_msg + 6 + n, rsa_key_len );
+
+ ssl->out_msglen = 6 + n + rsa_key_len;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_SERVER_KEY_EXCHANGE;
+
+ ssl->state++;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) );
+
+ return( 0 );
+#endif
+}
+
+static int ssl_write_server_hello_done( ssl_context *ssl )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) );
+
+ ssl->out_msglen = 4;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_SERVER_HELLO_DONE;
+
+ ssl->state++;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) );
+
+ return( 0 );
+}
+
+static int ssl_parse_client_key_exchange( ssl_context *ssl )
+{
+ int ret;
+ size_t i, n = 0;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
+
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+ }
+
+ if( ssl->in_msg[0] != SSL_HS_CLIENT_KEY_EXCHANGE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+ }
+
+ if( ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_DES_CBC_SHA ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ||
+ ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+ {
+#if !defined(POLARSSL_DHM_C)
+ SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) );
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+#else
+ /*
+ * Receive G^Y mod P, premaster = (G^Y)^X mod P
+ */
+ n = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+
+ if( n < 1 || n > ssl->handshake->dhm_ctx.len ||
+ n + 6 != ssl->in_hslen )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+ }
+
+ if( ( ret = dhm_read_public( &ssl->handshake->dhm_ctx,
+ ssl->in_msg + 6, n ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "dhm_read_public", ret );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP );
+ }
+
+ SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY );
+
+ ssl->handshake->pmslen = ssl->handshake->dhm_ctx.len;
+
+ if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
+ ssl->handshake->premaster,
+ &ssl->handshake->pmslen ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS );
+ }
+
+ SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K );
+#endif
+ }
+ else
+ {
+ if( ssl->rsa_key == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "got no private key" ) );
+ return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+ }
+
+ /*
+ * Decrypt the premaster using own private RSA key
+ */
+ i = 4;
+ if( ssl->rsa_key )
+ n = ssl->rsa_key_len( ssl->rsa_key );
+ ssl->handshake->pmslen = 48;
+
+ if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
+ {
+ i += 2;
+ if( ssl->in_msg[4] != ( ( n >> 8 ) & 0xFF ) ||
+ ssl->in_msg[5] != ( ( n ) & 0xFF ) )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+ }
+ }
+
+ if( ssl->in_hslen != i + n )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+ }
+
+ if( ssl->rsa_key ) {
+ ret = ssl->rsa_decrypt( ssl->rsa_key, RSA_PRIVATE,
+ &ssl->handshake->pmslen,
+ ssl->in_msg + i,
+ ssl->handshake->premaster,
+ sizeof(ssl->handshake->premaster) );
+ }
+
+ if( ret != 0 || ssl->handshake->pmslen != 48 ||
+ ssl->handshake->premaster[0] != ssl->max_major_ver ||
+ ssl->handshake->premaster[1] != ssl->max_minor_ver )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+
+ /*
+ * Protection against Bleichenbacher's attack:
+ * invalid PKCS#1 v1.5 padding must not cause
+ * the connection to end immediately; instead,
+ * send a bad_record_mac later in the handshake.
+ */
+ ssl->handshake->pmslen = 48;
+
+ ret = ssl->f_rng( ssl->p_rng, ssl->handshake->premaster,
+ ssl->handshake->pmslen );
+ if( ret != 0 )
+ return( ret );
+ }
+ }
+
+ if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+ return( ret );
+ }
+
+ ssl->state++;
+
+ SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) );
+
+ return( 0 );
+}
+
+static int ssl_parse_certificate_verify( ssl_context *ssl )
+{
+ int ret;
+ size_t n = 0, n1, n2;
+ unsigned char hash[48];
+ int hash_id;
+ unsigned int hashlen;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
+
+ if( ssl->session_negotiate->peer_cert == NULL )
+ {
+ SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+ ssl->handshake->calc_verify( ssl, hash );
+
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ ssl->state++;
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+ }
+
+ if( ssl->in_msg[0] != SSL_HS_CERTIFICATE_VERIFY )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+ }
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+ {
+ /*
+ * As server we know we either have SSL_HASH_SHA384 or
+ * SSL_HASH_SHA256
+ */
+ if( ssl->in_msg[4] != ssl->handshake->verify_sig_alg ||
+ ssl->in_msg[5] != SSL_SIG_RSA )
+ {
+ SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg for verify message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+ }
+
+ if( ssl->handshake->verify_sig_alg == SSL_HASH_SHA384 )
+ {
+ hashlen = 48;
+ hash_id = SIG_RSA_SHA384;
+ }
+ else
+ {
+ hashlen = 32;
+ hash_id = SIG_RSA_SHA256;
+ }
+
+ n += 2;
+ }
+ else
+ {
+ hashlen = 36;
+ hash_id = SIG_RSA_RAW;
+ }
+
+ n1 = ssl->session_negotiate->peer_cert->rsa.len;
+ n2 = ( ssl->in_msg[4 + n] << 8 ) | ssl->in_msg[5 + n];
+
+ if( n + n1 + 6 != ssl->in_hslen || n1 != n2 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+ }
+
+ ret = rsa_pkcs1_verify( &ssl->session_negotiate->peer_cert->rsa, RSA_PUBLIC,
+ hash_id, hashlen, hash, ssl->in_msg + 6 + n );
+ if( ret != 0 )
+ {
+ SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) );
+
+ return( 0 );
+}
+
+/*
+ * SSL handshake -- server side -- single step
+ */
+int ssl_handshake_server_step( ssl_context *ssl )
+{
+ int ret = 0;
+
+ if( ssl->state == SSL_HANDSHAKE_OVER )
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+ SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) );
+
+ if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+ return( ret );
+
+ switch( ssl->state )
+ {
+ case SSL_HELLO_REQUEST:
+ ssl->state = SSL_CLIENT_HELLO;
+ break;
+
+ /*
+ * <== ClientHello
+ */
+ case SSL_CLIENT_HELLO:
+ ret = ssl_parse_client_hello( ssl );
+ break;
+
+ /*
+ * ==> ServerHello
+ * Certificate
+ * ( ServerKeyExchange )
+ * ( CertificateRequest )
+ * ServerHelloDone
+ */
+ case SSL_SERVER_HELLO:
+ ret = ssl_write_server_hello( ssl );
+ break;
+
+ case SSL_SERVER_CERTIFICATE:
+ ret = ssl_write_certificate( ssl );
+ break;
+
+ case SSL_SERVER_KEY_EXCHANGE:
+ ret = ssl_write_server_key_exchange( ssl );
+ break;
+
+ case SSL_CERTIFICATE_REQUEST:
+ ret = ssl_write_certificate_request( ssl );
+ break;
+
+ case SSL_SERVER_HELLO_DONE:
+ ret = ssl_write_server_hello_done( ssl );
+ break;
+
+ /*
+ * <== ( Certificate/Alert )
+ * ClientKeyExchange
+ * ( CertificateVerify )
+ * ChangeCipherSpec
+ * Finished
+ */
+ case SSL_CLIENT_CERTIFICATE:
+ ret = ssl_parse_certificate( ssl );
+ break;
+
+ case SSL_CLIENT_KEY_EXCHANGE:
+ ret = ssl_parse_client_key_exchange( ssl );
+ break;
+
+ case SSL_CERTIFICATE_VERIFY:
+ ret = ssl_parse_certificate_verify( ssl );
+ break;
+
+ case SSL_CLIENT_CHANGE_CIPHER_SPEC:
+ ret = ssl_parse_change_cipher_spec( ssl );
+ break;
+
+ case SSL_CLIENT_FINISHED:
+ ret = ssl_parse_finished( ssl );
+ break;
+
+ /*
+ * ==> ChangeCipherSpec
+ * Finished
+ */
+ case SSL_SERVER_CHANGE_CIPHER_SPEC:
+ ret = ssl_write_change_cipher_spec( ssl );
+ break;
+
+ case SSL_SERVER_FINISHED:
+ ret = ssl_write_finished( ssl );
+ break;
+
+ case SSL_FLUSH_BUFFERS:
+ SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
+ ssl->state = SSL_HANDSHAKE_WRAPUP;
+ break;
+
+ case SSL_HANDSHAKE_WRAPUP:
+ ssl_handshake_wrapup( ssl );
+ break;
+
+ default:
+ SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ return( ret );
+}
+#endif
diff --git a/polarssl/ssl_tls.c b/polarssl/ssl_tls.c
new file mode 100644
index 0000000..cde6795
--- /dev/null
+++ b/polarssl/ssl_tls.c
@@ -0,0 +1,3991 @@
+/*
+ * SSLv3/TLSv1 shared functions
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The SSL 3.0 specification was drafted by Netscape in 1996,
+ * and became an IETF standard in 1999.
+ *
+ * http://wp.netscape.com/eng/ssl3/
+ * http://www.ietf.org/rfc/rfc2246.txt
+ * http://www.ietf.org/rfc/rfc4346.txt
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SSL_TLS_C)
+
+#include "polarssl/aes.h"
+#include "polarssl/arc4.h"
+#include "polarssl/camellia.h"
+#include "polarssl/des.h"
+#include "polarssl/debug.h"
+#include "polarssl/ssl.h"
+#include "polarssl/sha2.h"
+
+#if defined(POLARSSL_GCM_C)
+#include "polarssl/gcm.h"
+#endif
+
+#include
+#include
+
+#if defined _MSC_VER && !defined strcasecmp
+#define strcasecmp _stricmp
+#endif
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+int (*ssl_hw_record_init)(ssl_context *ssl,
+ const unsigned char *key_enc, const unsigned char *key_dec,
+ const unsigned char *iv_enc, const unsigned char *iv_dec,
+ const unsigned char *mac_enc, const unsigned char *mac_dec) = NULL;
+int (*ssl_hw_record_reset)(ssl_context *ssl) = NULL;
+int (*ssl_hw_record_write)(ssl_context *ssl) = NULL;
+int (*ssl_hw_record_read)(ssl_context *ssl) = NULL;
+int (*ssl_hw_record_finish)(ssl_context *ssl) = NULL;
+#endif
+
+static int ssl_rsa_decrypt( void *ctx, int mode, size_t *olen,
+ const unsigned char *input, unsigned char *output,
+ size_t output_max_len )
+{
+ return rsa_pkcs1_decrypt( (rsa_context *) ctx, mode, olen, input, output,
+ output_max_len );
+}
+
+static int ssl_rsa_sign( void *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ int mode, int hash_id, unsigned int hashlen,
+ const unsigned char *hash, unsigned char *sig )
+{
+ return rsa_pkcs1_sign( (rsa_context *) ctx, f_rng, p_rng, mode, hash_id,
+ hashlen, hash, sig );
+}
+
+static size_t ssl_rsa_key_len( void *ctx )
+{
+ return ( (rsa_context *) ctx )->len;
+}
+
+/*
+ * Key material generation
+ */
+static int ssl3_prf( unsigned char *secret, size_t slen, char *label,
+ unsigned char *random, size_t rlen,
+ unsigned char *dstbuf, size_t dlen )
+{
+ size_t i;
+ md5_context md5;
+ sha1_context sha1;
+ unsigned char padding[16];
+ unsigned char sha1sum[20];
+ ((void)label);
+
+ /*
+ * SSLv3:
+ * block =
+ * MD5( secret + SHA1( 'A' + secret + random ) ) +
+ * MD5( secret + SHA1( 'BB' + secret + random ) ) +
+ * MD5( secret + SHA1( 'CCC' + secret + random ) ) +
+ * ...
+ */
+ for( i = 0; i < dlen / 16; i++ )
+ {
+ memset( padding, 'A' + i, 1 + i );
+
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, padding, 1 + i );
+ sha1_update( &sha1, secret, slen );
+ sha1_update( &sha1, random, rlen );
+ sha1_finish( &sha1, sha1sum );
+
+ md5_starts( &md5 );
+ md5_update( &md5, secret, slen );
+ md5_update( &md5, sha1sum, 20 );
+ md5_finish( &md5, dstbuf + i * 16 );
+ }
+
+ memset( &md5, 0, sizeof( md5 ) );
+ memset( &sha1, 0, sizeof( sha1 ) );
+
+ memset( padding, 0, sizeof( padding ) );
+ memset( sha1sum, 0, sizeof( sha1sum ) );
+
+ return( 0 );
+}
+
+static int tls1_prf( unsigned char *secret, size_t slen, char *label,
+ unsigned char *random, size_t rlen,
+ unsigned char *dstbuf, size_t dlen )
+{
+ size_t nb, hs;
+ size_t i, j, k;
+ unsigned char *S1, *S2;
+ unsigned char tmp[128];
+ unsigned char h_i[20];
+
+ if( sizeof( tmp ) < 20 + strlen( label ) + rlen )
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+ hs = ( slen + 1 ) / 2;
+ S1 = secret;
+ S2 = secret + slen - hs;
+
+ nb = strlen( label );
+ memcpy( tmp + 20, label, nb );
+ memcpy( tmp + 20 + nb, random, rlen );
+ nb += rlen;
+
+ /*
+ * First compute P_md5(secret,label+random)[0..dlen]
+ */
+ md5_hmac( S1, hs, tmp + 20, nb, 4 + tmp );
+
+ for( i = 0; i < dlen; i += 16 )
+ {
+ md5_hmac( S1, hs, 4 + tmp, 16 + nb, h_i );
+ md5_hmac( S1, hs, 4 + tmp, 16, 4 + tmp );
+
+ k = ( i + 16 > dlen ) ? dlen % 16 : 16;
+
+ for( j = 0; j < k; j++ )
+ dstbuf[i + j] = h_i[j];
+ }
+
+ /*
+ * XOR out with P_sha1(secret,label+random)[0..dlen]
+ */
+ sha1_hmac( S2, hs, tmp + 20, nb, tmp );
+
+ for( i = 0; i < dlen; i += 20 )
+ {
+ sha1_hmac( S2, hs, tmp, 20 + nb, h_i );
+ sha1_hmac( S2, hs, tmp, 20, tmp );
+
+ k = ( i + 20 > dlen ) ? dlen % 20 : 20;
+
+ for( j = 0; j < k; j++ )
+ dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] );
+ }
+
+ memset( tmp, 0, sizeof( tmp ) );
+ memset( h_i, 0, sizeof( h_i ) );
+
+ return( 0 );
+}
+
+static int tls_prf_sha256( unsigned char *secret, size_t slen, char *label,
+ unsigned char *random, size_t rlen,
+ unsigned char *dstbuf, size_t dlen )
+{
+ size_t nb;
+ size_t i, j, k;
+ unsigned char tmp[128];
+ unsigned char h_i[32];
+
+ if( sizeof( tmp ) < 32 + strlen( label ) + rlen )
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+ nb = strlen( label );
+ memcpy( tmp + 32, label, nb );
+ memcpy( tmp + 32 + nb, random, rlen );
+ nb += rlen;
+
+ /*
+ * Compute P_(secret, label + random)[0..dlen]
+ */
+ sha2_hmac( secret, slen, tmp + 32, nb, tmp, 0 );
+
+ for( i = 0; i < dlen; i += 32 )
+ {
+ sha2_hmac( secret, slen, tmp, 32 + nb, h_i, 0 );
+ sha2_hmac( secret, slen, tmp, 32, tmp, 0 );
+
+ k = ( i + 32 > dlen ) ? dlen % 32 : 32;
+
+ for( j = 0; j < k; j++ )
+ dstbuf[i + j] = h_i[j];
+ }
+
+ memset( tmp, 0, sizeof( tmp ) );
+ memset( h_i, 0, sizeof( h_i ) );
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_SHA4_C)
+static int tls_prf_sha384( unsigned char *secret, size_t slen, char *label,
+ unsigned char *random, size_t rlen,
+ unsigned char *dstbuf, size_t dlen )
+{
+ size_t nb;
+ size_t i, j, k;
+ unsigned char tmp[128];
+ unsigned char h_i[48];
+
+ if( sizeof( tmp ) < 48 + strlen( label ) + rlen )
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+ nb = strlen( label );
+ memcpy( tmp + 48, label, nb );
+ memcpy( tmp + 48 + nb, random, rlen );
+ nb += rlen;
+
+ /*
+ * Compute P_(secret, label + random)[0..dlen]
+ */
+ sha4_hmac( secret, slen, tmp + 48, nb, tmp, 1 );
+
+ for( i = 0; i < dlen; i += 48 )
+ {
+ sha4_hmac( secret, slen, tmp, 48 + nb, h_i, 1 );
+ sha4_hmac( secret, slen, tmp, 48, tmp, 1 );
+
+ k = ( i + 48 > dlen ) ? dlen % 48 : 48;
+
+ for( j = 0; j < k; j++ )
+ dstbuf[i + j] = h_i[j];
+ }
+
+ memset( tmp, 0, sizeof( tmp ) );
+ memset( h_i, 0, sizeof( h_i ) );
+
+ return( 0 );
+}
+#endif
+
+static void ssl_update_checksum_start(ssl_context *, unsigned char *, size_t);
+static void ssl_update_checksum_md5sha1(ssl_context *, unsigned char *, size_t);
+static void ssl_update_checksum_sha256(ssl_context *, unsigned char *, size_t);
+
+static void ssl_calc_verify_ssl(ssl_context *,unsigned char *);
+static void ssl_calc_verify_tls(ssl_context *,unsigned char *);
+static void ssl_calc_verify_tls_sha256(ssl_context *,unsigned char *);
+
+static void ssl_calc_finished_ssl(ssl_context *,unsigned char *,int);
+static void ssl_calc_finished_tls(ssl_context *,unsigned char *,int);
+static void ssl_calc_finished_tls_sha256(ssl_context *,unsigned char *,int);
+
+#if defined(POLARSSL_SHA4_C)
+static void ssl_update_checksum_sha384(ssl_context *, unsigned char *, size_t);
+static void ssl_calc_verify_tls_sha384(ssl_context *,unsigned char *);
+static void ssl_calc_finished_tls_sha384(ssl_context *,unsigned char *,int);
+#endif
+
+int ssl_derive_keys( ssl_context *ssl )
+{
+ unsigned char tmp[64];
+ unsigned char keyblk[256];
+ unsigned char *key1;
+ unsigned char *key2;
+ unsigned int iv_copy_len;
+ ssl_session *session = ssl->session_negotiate;
+ ssl_transform *transform = ssl->transform_negotiate;
+ ssl_handshake_params *handshake = ssl->handshake;
+
+ SSL_DEBUG_MSG( 2, ( "=> derive keys" ) );
+
+ /*
+ * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions
+ */
+ if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ handshake->tls_prf = ssl3_prf;
+ handshake->calc_verify = ssl_calc_verify_ssl;
+ handshake->calc_finished = ssl_calc_finished_ssl;
+ }
+ else if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
+ {
+ handshake->tls_prf = tls1_prf;
+ handshake->calc_verify = ssl_calc_verify_tls;
+ handshake->calc_finished = ssl_calc_finished_tls;
+ }
+#if defined(POLARSSL_SHA4_C)
+ else if( session->ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 ||
+ session->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+ {
+ handshake->tls_prf = tls_prf_sha384;
+ handshake->calc_verify = ssl_calc_verify_tls_sha384;
+ handshake->calc_finished = ssl_calc_finished_tls_sha384;
+ }
+#endif
+ else
+ {
+ handshake->tls_prf = tls_prf_sha256;
+ handshake->calc_verify = ssl_calc_verify_tls_sha256;
+ handshake->calc_finished = ssl_calc_finished_tls_sha256;
+ }
+
+ /*
+ * SSLv3:
+ * master =
+ * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) +
+ * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) +
+ * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) )
+ *
+ * TLSv1:
+ * master = PRF( premaster, "master secret", randbytes )[0..47]
+ */
+ if( handshake->resume == 0 )
+ {
+ SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster,
+ handshake->pmslen );
+
+ handshake->tls_prf( handshake->premaster, handshake->pmslen,
+ "master secret",
+ handshake->randbytes, 64, session->master, 48 );
+
+ memset( handshake->premaster, 0, sizeof( handshake->premaster ) );
+ }
+ else
+ SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) );
+
+ /*
+ * Swap the client and server random values.
+ */
+ memcpy( tmp, handshake->randbytes, 64 );
+ memcpy( handshake->randbytes, tmp + 32, 32 );
+ memcpy( handshake->randbytes + 32, tmp, 32 );
+ memset( tmp, 0, sizeof( tmp ) );
+
+ /*
+ * SSLv3:
+ * key block =
+ * MD5( master + SHA1( 'A' + master + randbytes ) ) +
+ * MD5( master + SHA1( 'BB' + master + randbytes ) ) +
+ * MD5( master + SHA1( 'CCC' + master + randbytes ) ) +
+ * MD5( master + SHA1( 'DDDD' + master + randbytes ) ) +
+ * ...
+ *
+ * TLSv1:
+ * key block = PRF( master, "key expansion", randbytes )
+ */
+ handshake->tls_prf( session->master, 48, "key expansion",
+ handshake->randbytes, 64, keyblk, 256 );
+
+ SSL_DEBUG_MSG( 3, ( "ciphersuite = %s",
+ ssl_get_ciphersuite_name( session->ciphersuite ) ) );
+ SSL_DEBUG_BUF( 3, "master secret", session->master, 48 );
+ SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 );
+ SSL_DEBUG_BUF( 4, "key block", keyblk, 256 );
+
+ memset( handshake->randbytes, 0, sizeof( handshake->randbytes ) );
+
+ /*
+ * Determine the appropriate key, IV and MAC length.
+ */
+ switch( session->ciphersuite )
+ {
+#if defined(POLARSSL_ARC4_C)
+ case TLS_RSA_WITH_RC4_128_MD5:
+ transform->keylen = 16; transform->minlen = 16;
+ transform->ivlen = 0; transform->maclen = 16;
+ break;
+
+ case TLS_RSA_WITH_RC4_128_SHA:
+ transform->keylen = 16; transform->minlen = 20;
+ transform->ivlen = 0; transform->maclen = 20;
+ break;
+#endif
+
+#if defined(POLARSSL_DES_C)
+ case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+ case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ transform->keylen = 24; transform->minlen = 24;
+ transform->ivlen = 8; transform->maclen = 20;
+ break;
+#endif
+
+#if defined(POLARSSL_AES_C)
+ case TLS_RSA_WITH_AES_128_CBC_SHA:
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ transform->keylen = 16; transform->minlen = 32;
+ transform->ivlen = 16; transform->maclen = 20;
+ break;
+
+ case TLS_RSA_WITH_AES_256_CBC_SHA:
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ transform->keylen = 32; transform->minlen = 32;
+ transform->ivlen = 16; transform->maclen = 20;
+ break;
+
+#if defined(POLARSSL_SHA2_C)
+ case TLS_RSA_WITH_AES_128_CBC_SHA256:
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+ transform->keylen = 16; transform->minlen = 32;
+ transform->ivlen = 16; transform->maclen = 32;
+ break;
+
+ case TLS_RSA_WITH_AES_256_CBC_SHA256:
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+ transform->keylen = 32; transform->minlen = 32;
+ transform->ivlen = 16; transform->maclen = 32;
+ break;
+#endif
+#if defined(POLARSSL_GCM_C)
+ case TLS_RSA_WITH_AES_128_GCM_SHA256:
+ case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+ transform->keylen = 16; transform->minlen = 1;
+ transform->ivlen = 12; transform->maclen = 0;
+ transform->fixed_ivlen = 4;
+ break;
+
+ case TLS_RSA_WITH_AES_256_GCM_SHA384:
+ case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+ transform->keylen = 32; transform->minlen = 1;
+ transform->ivlen = 12; transform->maclen = 0;
+ transform->fixed_ivlen = 4;
+ break;
+#endif
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+ case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ transform->keylen = 16; transform->minlen = 32;
+ transform->ivlen = 16; transform->maclen = 20;
+ break;
+
+ case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ transform->keylen = 32; transform->minlen = 32;
+ transform->ivlen = 16; transform->maclen = 20;
+ break;
+
+#if defined(POLARSSL_SHA2_C)
+ case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ transform->keylen = 16; transform->minlen = 32;
+ transform->ivlen = 16; transform->maclen = 32;
+ break;
+
+ case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ transform->keylen = 32; transform->minlen = 32;
+ transform->ivlen = 16; transform->maclen = 32;
+ break;
+#endif
+#endif
+
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ case TLS_RSA_WITH_NULL_MD5:
+ transform->keylen = 0; transform->minlen = 0;
+ transform->ivlen = 0; transform->maclen = 16;
+ break;
+
+ case TLS_RSA_WITH_NULL_SHA:
+ transform->keylen = 0; transform->minlen = 0;
+ transform->ivlen = 0; transform->maclen = 20;
+ break;
+
+ case TLS_RSA_WITH_NULL_SHA256:
+ transform->keylen = 0; transform->minlen = 0;
+ transform->ivlen = 0; transform->maclen = 32;
+ break;
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+#if defined(POLARSSL_DES_C)
+ case TLS_RSA_WITH_DES_CBC_SHA:
+ case TLS_DHE_RSA_WITH_DES_CBC_SHA:
+ transform->keylen = 8; transform->minlen = 8;
+ transform->ivlen = 8; transform->maclen = 20;
+ break;
+#endif
+#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
+
+ default:
+ SSL_DEBUG_MSG( 1, ( "ciphersuite %s is not available",
+ ssl_get_ciphersuite_name( session->ciphersuite ) ) );
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+
+ SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d",
+ transform->keylen, transform->minlen, transform->ivlen,
+ transform->maclen ) );
+
+ /*
+ * Finally setup the cipher contexts, IVs and MAC secrets.
+ */
+ if( ssl->endpoint == SSL_IS_CLIENT )
+ {
+ key1 = keyblk + transform->maclen * 2;
+ key2 = keyblk + transform->maclen * 2 + transform->keylen;
+
+ memcpy( transform->mac_enc, keyblk, transform->maclen );
+ memcpy( transform->mac_dec, keyblk + transform->maclen,
+ transform->maclen );
+
+ /*
+ * This is not used in TLS v1.1.
+ */
+ iv_copy_len = ( transform->fixed_ivlen ) ?
+ transform->fixed_ivlen : transform->ivlen;
+ memcpy( transform->iv_enc, key2 + transform->keylen, iv_copy_len );
+ memcpy( transform->iv_dec, key2 + transform->keylen + iv_copy_len,
+ iv_copy_len );
+ }
+ else
+ {
+ key1 = keyblk + transform->maclen * 2 + transform->keylen;
+ key2 = keyblk + transform->maclen * 2;
+
+ memcpy( transform->mac_dec, keyblk, transform->maclen );
+ memcpy( transform->mac_enc, keyblk + transform->maclen,
+ transform->maclen );
+
+ /*
+ * This is not used in TLS v1.1.
+ */
+ iv_copy_len = ( transform->fixed_ivlen ) ?
+ transform->fixed_ivlen : transform->ivlen;
+ memcpy( transform->iv_dec, key1 + transform->keylen, iv_copy_len );
+ memcpy( transform->iv_enc, key1 + transform->keylen + iv_copy_len,
+ iv_copy_len );
+ }
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+ if( ssl_hw_record_init != NULL)
+ {
+ int ret = 0;
+
+ SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_init()" ) );
+
+ if( ( ret = ssl_hw_record_init( ssl, key1, key2, transform->iv_enc,
+ transform->iv_dec, transform->mac_enc,
+ transform->mac_dec ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_hw_record_init", ret );
+ return POLARSSL_ERR_SSL_HW_ACCEL_FAILED;
+ }
+ }
+#endif
+
+ switch( session->ciphersuite )
+ {
+#if defined(POLARSSL_ARC4_C)
+ case TLS_RSA_WITH_RC4_128_MD5:
+ case TLS_RSA_WITH_RC4_128_SHA:
+ arc4_setup( (arc4_context *) transform->ctx_enc, key1,
+ transform->keylen );
+ arc4_setup( (arc4_context *) transform->ctx_dec, key2,
+ transform->keylen );
+ break;
+#endif
+
+#if defined(POLARSSL_DES_C)
+ case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+ case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ des3_set3key_enc( (des3_context *) transform->ctx_enc, key1 );
+ des3_set3key_dec( (des3_context *) transform->ctx_dec, key2 );
+ break;
+#endif
+
+#if defined(POLARSSL_AES_C)
+ case TLS_RSA_WITH_AES_128_CBC_SHA:
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ case TLS_RSA_WITH_AES_128_CBC_SHA256:
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+ aes_setkey_enc( (aes_context *) transform->ctx_enc, key1, 128 );
+ aes_setkey_dec( (aes_context *) transform->ctx_dec, key2, 128 );
+ break;
+
+ case TLS_RSA_WITH_AES_256_CBC_SHA:
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ case TLS_RSA_WITH_AES_256_CBC_SHA256:
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+ aes_setkey_enc( (aes_context *) transform->ctx_enc, key1, 256 );
+ aes_setkey_dec( (aes_context *) transform->ctx_dec, key2, 256 );
+ break;
+
+#if defined(POLARSSL_GCM_C)
+ case TLS_RSA_WITH_AES_128_GCM_SHA256:
+ case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+ gcm_init( (gcm_context *) transform->ctx_enc, key1, 128 );
+ gcm_init( (gcm_context *) transform->ctx_dec, key2, 128 );
+ break;
+
+ case TLS_RSA_WITH_AES_256_GCM_SHA384:
+ case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+ gcm_init( (gcm_context *) transform->ctx_enc, key1, 256 );
+ gcm_init( (gcm_context *) transform->ctx_dec, key2, 256 );
+ break;
+#endif
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+ case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ camellia_setkey_enc( (camellia_context *) transform->ctx_enc, key1, 128 );
+ camellia_setkey_dec( (camellia_context *) transform->ctx_dec, key2, 128 );
+ break;
+
+ case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ camellia_setkey_enc( (camellia_context *) transform->ctx_enc, key1, 256 );
+ camellia_setkey_dec( (camellia_context *) transform->ctx_dec, key2, 256 );
+ break;
+#endif
+
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ case TLS_RSA_WITH_NULL_MD5:
+ case TLS_RSA_WITH_NULL_SHA:
+ case TLS_RSA_WITH_NULL_SHA256:
+ break;
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+#if defined(POLARSSL_DES_C)
+ case TLS_RSA_WITH_DES_CBC_SHA:
+ case TLS_DHE_RSA_WITH_DES_CBC_SHA:
+ des_setkey_enc( (des_context *) transform->ctx_enc, key1 );
+ des_setkey_dec( (des_context *) transform->ctx_dec, key2 );
+ break;
+#endif
+#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
+
+ default:
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+
+ memset( keyblk, 0, sizeof( keyblk ) );
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+ // Initialize compression
+ //
+ if( session->compression == SSL_COMPRESS_DEFLATE )
+ {
+ SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) );
+
+ memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) );
+ memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) );
+
+ if( deflateInit( &transform->ctx_deflate, Z_DEFAULT_COMPRESSION ) != Z_OK ||
+ inflateInit( &transform->ctx_inflate ) != Z_OK )
+ {
+ SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) );
+ return( POLARSSL_ERR_SSL_COMPRESSION_FAILED );
+ }
+ }
+#endif /* POLARSSL_ZLIB_SUPPORT */
+
+ SSL_DEBUG_MSG( 2, ( "<= derive keys" ) );
+
+ return( 0 );
+}
+
+void ssl_calc_verify_ssl( ssl_context *ssl, unsigned char hash[36] )
+{
+ md5_context md5;
+ sha1_context sha1;
+ unsigned char pad_1[48];
+ unsigned char pad_2[48];
+
+ SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) );
+
+ memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) );
+ memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) );
+
+ memset( pad_1, 0x36, 48 );
+ memset( pad_2, 0x5C, 48 );
+
+ md5_update( &md5, ssl->session_negotiate->master, 48 );
+ md5_update( &md5, pad_1, 48 );
+ md5_finish( &md5, hash );
+
+ md5_starts( &md5 );
+ md5_update( &md5, ssl->session_negotiate->master, 48 );
+ md5_update( &md5, pad_2, 48 );
+ md5_update( &md5, hash, 16 );
+ md5_finish( &md5, hash );
+
+ sha1_update( &sha1, ssl->session_negotiate->master, 48 );
+ sha1_update( &sha1, pad_1, 40 );
+ sha1_finish( &sha1, hash + 16 );
+
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, ssl->session_negotiate->master, 48 );
+ sha1_update( &sha1, pad_2, 40 );
+ sha1_update( &sha1, hash + 16, 20 );
+ sha1_finish( &sha1, hash + 16 );
+
+ SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 );
+ SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
+
+ return;
+}
+
+void ssl_calc_verify_tls( ssl_context *ssl, unsigned char hash[36] )
+{
+ md5_context md5;
+ sha1_context sha1;
+
+ SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) );
+
+ memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) );
+ memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) );
+
+ md5_finish( &md5, hash );
+ sha1_finish( &sha1, hash + 16 );
+
+ SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 );
+ SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
+
+ return;
+}
+
+void ssl_calc_verify_tls_sha256( ssl_context *ssl, unsigned char hash[32] )
+{
+ sha2_context sha2;
+
+ SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) );
+
+ memcpy( &sha2, &ssl->handshake->fin_sha2, sizeof(sha2_context) );
+ sha2_finish( &sha2, hash );
+
+ SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 );
+ SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
+
+ return;
+}
+
+#if defined(POLARSSL_SHA4_C)
+void ssl_calc_verify_tls_sha384( ssl_context *ssl, unsigned char hash[48] )
+{
+ sha4_context sha4;
+
+ SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) );
+
+ memcpy( &sha4, &ssl->handshake->fin_sha4, sizeof(sha4_context) );
+ sha4_finish( &sha4, hash );
+
+ SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 );
+ SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
+
+ return;
+}
+#endif
+
+/*
+ * SSLv3.0 MAC functions
+ */
+static void ssl_mac_md5( unsigned char *secret,
+ unsigned char *buf, size_t len,
+ unsigned char *ctr, int type )
+{
+ unsigned char header[11];
+ unsigned char padding[48];
+ md5_context md5;
+
+ memcpy( header, ctr, 8 );
+ header[ 8] = (unsigned char) type;
+ header[ 9] = (unsigned char)( len >> 8 );
+ header[10] = (unsigned char)( len );
+
+ memset( padding, 0x36, 48 );
+ md5_starts( &md5 );
+ md5_update( &md5, secret, 16 );
+ md5_update( &md5, padding, 48 );
+ md5_update( &md5, header, 11 );
+ md5_update( &md5, buf, len );
+ md5_finish( &md5, buf + len );
+
+ memset( padding, 0x5C, 48 );
+ md5_starts( &md5 );
+ md5_update( &md5, secret, 16 );
+ md5_update( &md5, padding, 48 );
+ md5_update( &md5, buf + len, 16 );
+ md5_finish( &md5, buf + len );
+}
+
+static void ssl_mac_sha1( unsigned char *secret,
+ unsigned char *buf, size_t len,
+ unsigned char *ctr, int type )
+{
+ unsigned char header[11];
+ unsigned char padding[40];
+ sha1_context sha1;
+
+ memcpy( header, ctr, 8 );
+ header[ 8] = (unsigned char) type;
+ header[ 9] = (unsigned char)( len >> 8 );
+ header[10] = (unsigned char)( len );
+
+ memset( padding, 0x36, 40 );
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, secret, 20 );
+ sha1_update( &sha1, padding, 40 );
+ sha1_update( &sha1, header, 11 );
+ sha1_update( &sha1, buf, len );
+ sha1_finish( &sha1, buf + len );
+
+ memset( padding, 0x5C, 40 );
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, secret, 20 );
+ sha1_update( &sha1, padding, 40 );
+ sha1_update( &sha1, buf + len, 20 );
+ sha1_finish( &sha1, buf + len );
+}
+
+static void ssl_mac_sha2( unsigned char *secret,
+ unsigned char *buf, size_t len,
+ unsigned char *ctr, int type )
+{
+ unsigned char header[11];
+ unsigned char padding[32];
+ sha2_context sha2;
+
+ memcpy( header, ctr, 8 );
+ header[ 8] = (unsigned char) type;
+ header[ 9] = (unsigned char)( len >> 8 );
+ header[10] = (unsigned char)( len );
+
+ memset( padding, 0x36, 32 );
+ sha2_starts( &sha2, 0 );
+ sha2_update( &sha2, secret, 32 );
+ sha2_update( &sha2, padding, 32 );
+ sha2_update( &sha2, header, 11 );
+ sha2_update( &sha2, buf, len );
+ sha2_finish( &sha2, buf + len );
+
+ memset( padding, 0x5C, 32 );
+ sha2_starts( &sha2, 0 );
+ sha2_update( &sha2, secret, 32 );
+ sha2_update( &sha2, padding, 32 );
+ sha2_update( &sha2, buf + len, 32 );
+ sha2_finish( &sha2, buf + len );
+}
+
+/*
+ * Encryption/decryption functions
+ */
+static int ssl_encrypt_buf( ssl_context *ssl )
+{
+ size_t i, padlen;
+
+ SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
+
+ /*
+ * Add MAC then encrypt
+ */
+ if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ if( ssl->transform_out->maclen == 16 )
+ ssl_mac_md5( ssl->transform_out->mac_enc,
+ ssl->out_msg, ssl->out_msglen,
+ ssl->out_ctr, ssl->out_msgtype );
+ else if( ssl->transform_out->maclen == 20 )
+ ssl_mac_sha1( ssl->transform_out->mac_enc,
+ ssl->out_msg, ssl->out_msglen,
+ ssl->out_ctr, ssl->out_msgtype );
+ else if( ssl->transform_out->maclen == 32 )
+ ssl_mac_sha2( ssl->transform_out->mac_enc,
+ ssl->out_msg, ssl->out_msglen,
+ ssl->out_ctr, ssl->out_msgtype );
+ else if( ssl->transform_out->maclen != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d",
+ ssl->transform_out->maclen ) );
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+ }
+ else
+ {
+ if( ssl->transform_out->maclen == 16 )
+ {
+ md5_context ctx;
+ md5_hmac_starts( &ctx, ssl->transform_out->mac_enc, 16 );
+ md5_hmac_update( &ctx, ssl->out_ctr, 13 );
+ md5_hmac_update( &ctx, ssl->out_msg, ssl->out_msglen );
+ md5_hmac_finish( &ctx, ssl->out_msg + ssl->out_msglen );
+ memset( &ctx, 0, sizeof(md5_context));
+ }
+ else if( ssl->transform_out->maclen == 20 )
+ {
+ sha1_context ctx;
+ sha1_hmac_starts( &ctx, ssl->transform_out->mac_enc, 20 );
+ sha1_hmac_update( &ctx, ssl->out_ctr, 13 );
+ sha1_hmac_update( &ctx, ssl->out_msg, ssl->out_msglen );
+ sha1_hmac_finish( &ctx, ssl->out_msg + ssl->out_msglen );
+ memset( &ctx, 0, sizeof(sha1_context));
+ }
+ else if( ssl->transform_out->maclen == 32 )
+ {
+ sha2_context ctx;
+ sha2_hmac_starts( &ctx, ssl->transform_out->mac_enc, 32, 0 );
+ sha2_hmac_update( &ctx, ssl->out_ctr, 13 );
+ sha2_hmac_update( &ctx, ssl->out_msg, ssl->out_msglen );
+ sha2_hmac_finish( &ctx, ssl->out_msg + ssl->out_msglen );
+ memset( &ctx, 0, sizeof(sha2_context));
+ }
+ else if( ssl->transform_out->maclen != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d",
+ ssl->transform_out->maclen ) );
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+ }
+
+ SSL_DEBUG_BUF( 4, "computed mac",
+ ssl->out_msg + ssl->out_msglen, ssl->transform_out->maclen );
+
+ ssl->out_msglen += ssl->transform_out->maclen;
+
+ if( ssl->transform_out->ivlen == 0 )
+ {
+ padlen = 0;
+
+ SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+ "including %d bytes of padding",
+ ssl->out_msglen, 0 ) );
+
+ SSL_DEBUG_BUF( 4, "before encrypt: output payload",
+ ssl->out_msg, ssl->out_msglen );
+
+#if defined(POLARSSL_ARC4_C)
+ if( ssl->session_out->ciphersuite == TLS_RSA_WITH_RC4_128_MD5 ||
+ ssl->session_out->ciphersuite == TLS_RSA_WITH_RC4_128_SHA )
+ {
+ arc4_crypt( (arc4_context *) ssl->transform_out->ctx_enc,
+ ssl->out_msglen, ssl->out_msg,
+ ssl->out_msg );
+ } else
+#endif
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ if( ssl->session_out->ciphersuite == TLS_RSA_WITH_NULL_MD5 ||
+ ssl->session_out->ciphersuite == TLS_RSA_WITH_NULL_SHA ||
+ ssl->session_out->ciphersuite == TLS_RSA_WITH_NULL_SHA256 )
+ {
+ } else
+#endif
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+ else if( ssl->transform_out->ivlen == 12 )
+ {
+ size_t enc_msglen;
+ unsigned char *enc_msg;
+ unsigned char add_data[13];
+ int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+
+ padlen = 0;
+ enc_msglen = ssl->out_msglen;
+
+ memcpy( add_data, ssl->out_ctr, 8 );
+ add_data[8] = ssl->out_msgtype;
+ add_data[9] = ssl->major_ver;
+ add_data[10] = ssl->minor_ver;
+ add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF;
+ add_data[12] = ssl->out_msglen & 0xFF;
+
+ SSL_DEBUG_BUF( 4, "additional data used for AEAD",
+ add_data, 13 );
+
+#if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C)
+
+ if( ssl->session_out->ciphersuite == TLS_RSA_WITH_AES_128_GCM_SHA256 ||
+ ssl->session_out->ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 ||
+ ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ||
+ ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+ {
+ /*
+ * Generate IV
+ */
+ ret = ssl->f_rng( ssl->p_rng,
+ ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
+ ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
+ if( ret != 0 )
+ return( ret );
+
+ /*
+ * Shift message for ivlen bytes and prepend IV
+ */
+ memmove( ssl->out_msg + ssl->transform_out->ivlen -
+ ssl->transform_out->fixed_ivlen,
+ ssl->out_msg, ssl->out_msglen );
+ memcpy( ssl->out_msg,
+ ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
+ ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
+
+ /*
+ * Fix pointer positions and message length with added IV
+ */
+ enc_msg = ssl->out_msg + ssl->transform_out->ivlen -
+ ssl->transform_out->fixed_ivlen;
+ enc_msglen = ssl->out_msglen;
+ ssl->out_msglen += ssl->transform_out->ivlen -
+ ssl->transform_out->fixed_ivlen;
+
+ SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+ "including %d bytes of padding",
+ ssl->out_msglen, 0 ) );
+
+ SSL_DEBUG_BUF( 4, "before encrypt: output payload",
+ ssl->out_msg, ssl->out_msglen );
+
+ /*
+ * Adjust for tag
+ */
+ ssl->out_msglen += 16;
+
+ gcm_crypt_and_tag( (gcm_context *) ssl->transform_out->ctx_enc,
+ GCM_ENCRYPT, enc_msglen,
+ ssl->transform_out->iv_enc, ssl->transform_out->ivlen,
+ add_data, 13,
+ enc_msg, enc_msg,
+ 16, enc_msg + enc_msglen );
+
+ SSL_DEBUG_BUF( 4, "after encrypt: tag",
+ enc_msg + enc_msglen, 16 );
+
+ } else
+#endif
+ return( ret );
+ }
+ else
+ {
+ unsigned char *enc_msg;
+ size_t enc_msglen;
+
+ padlen = ssl->transform_out->ivlen - ( ssl->out_msglen + 1 ) %
+ ssl->transform_out->ivlen;
+ if( padlen == ssl->transform_out->ivlen )
+ padlen = 0;
+
+ for( i = 0; i <= padlen; i++ )
+ ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen;
+
+ ssl->out_msglen += padlen + 1;
+
+ enc_msglen = ssl->out_msglen;
+ enc_msg = ssl->out_msg;
+
+ /*
+ * Prepend per-record IV for block cipher in TLS v1.1 and up as per
+ * Method 1 (6.2.3.2. in RFC4346 and RFC5246)
+ */
+ if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
+ {
+ /*
+ * Generate IV
+ */
+ int ret = ssl->f_rng( ssl->p_rng, ssl->transform_out->iv_enc,
+ ssl->transform_out->ivlen );
+ if( ret != 0 )
+ return( ret );
+
+ /*
+ * Shift message for ivlen bytes and prepend IV
+ */
+ memmove( ssl->out_msg + ssl->transform_out->ivlen, ssl->out_msg,
+ ssl->out_msglen );
+ memcpy( ssl->out_msg, ssl->transform_out->iv_enc,
+ ssl->transform_out->ivlen );
+
+ /*
+ * Fix pointer positions and message length with added IV
+ */
+ enc_msg = ssl->out_msg + ssl->transform_out->ivlen;
+ enc_msglen = ssl->out_msglen;
+ ssl->out_msglen += ssl->transform_out->ivlen;
+ }
+
+ SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+ "including %d bytes of IV and %d bytes of padding",
+ ssl->out_msglen, ssl->transform_out->ivlen, padlen + 1 ) );
+
+ SSL_DEBUG_BUF( 4, "before encrypt: output payload",
+ ssl->out_msg, ssl->out_msglen );
+
+ switch( ssl->transform_out->ivlen )
+ {
+#if defined(POLARSSL_DES_C)
+ case 8:
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+ if( ssl->session_out->ciphersuite == TLS_RSA_WITH_DES_CBC_SHA ||
+ ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_DES_CBC_SHA )
+ {
+ des_crypt_cbc( (des_context *) ssl->transform_out->ctx_enc,
+ DES_ENCRYPT, enc_msglen,
+ ssl->transform_out->iv_enc, enc_msg, enc_msg );
+ }
+ else
+#endif
+ des3_crypt_cbc( (des3_context *) ssl->transform_out->ctx_enc,
+ DES_ENCRYPT, enc_msglen,
+ ssl->transform_out->iv_enc, enc_msg, enc_msg );
+ break;
+#endif
+
+ case 16:
+#if defined(POLARSSL_AES_C)
+ if ( ssl->session_out->ciphersuite == TLS_RSA_WITH_AES_128_CBC_SHA ||
+ ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA ||
+ ssl->session_out->ciphersuite == TLS_RSA_WITH_AES_256_CBC_SHA ||
+ ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA ||
+ ssl->session_out->ciphersuite == TLS_RSA_WITH_AES_128_CBC_SHA256 ||
+ ssl->session_out->ciphersuite == TLS_RSA_WITH_AES_256_CBC_SHA256 ||
+ ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 ||
+ ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 )
+ {
+ aes_crypt_cbc( (aes_context *) ssl->transform_out->ctx_enc,
+ AES_ENCRYPT, enc_msglen,
+ ssl->transform_out->iv_enc, enc_msg, enc_msg);
+ break;
+ }
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+ if ( ssl->session_out->ciphersuite == TLS_RSA_WITH_CAMELLIA_128_CBC_SHA ||
+ ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA ||
+ ssl->session_out->ciphersuite == TLS_RSA_WITH_CAMELLIA_256_CBC_SHA ||
+ ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA ||
+ ssl->session_out->ciphersuite == TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 ||
+ ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 ||
+ ssl->session_out->ciphersuite == TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 ||
+ ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 )
+ {
+ camellia_crypt_cbc( (camellia_context *) ssl->transform_out->ctx_enc,
+ CAMELLIA_ENCRYPT, enc_msglen,
+ ssl->transform_out->iv_enc, enc_msg, enc_msg );
+ break;
+ }
+#endif
+
+ default:
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+ }
+
+ for( i = 8; i > 0; i-- )
+ if( ++ssl->out_ctr[i - 1] != 0 )
+ break;
+
+ SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) );
+
+ return( 0 );
+}
+
+/*
+ * TODO: Use digest version when integrated!
+ */
+#define POLARSSL_SSL_MAX_MAC_SIZE 32
+
+static int ssl_decrypt_buf( ssl_context *ssl )
+{
+ size_t i, padlen = 0, correct = 1;
+ unsigned char tmp[POLARSSL_SSL_MAX_MAC_SIZE];
+
+ SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
+
+ if( ssl->in_msglen < ssl->transform_in->minlen )
+ {
+ SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)",
+ ssl->in_msglen, ssl->transform_in->minlen ) );
+ return( POLARSSL_ERR_SSL_INVALID_MAC );
+ }
+
+ if( ssl->transform_in->ivlen == 0 )
+ {
+#if defined(POLARSSL_ARC4_C)
+ if( ssl->session_in->ciphersuite == TLS_RSA_WITH_RC4_128_MD5 ||
+ ssl->session_in->ciphersuite == TLS_RSA_WITH_RC4_128_SHA )
+ {
+ arc4_crypt( (arc4_context *) ssl->transform_in->ctx_dec,
+ ssl->in_msglen, ssl->in_msg,
+ ssl->in_msg );
+ } else
+#endif
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ if( ssl->session_in->ciphersuite == TLS_RSA_WITH_NULL_MD5 ||
+ ssl->session_in->ciphersuite == TLS_RSA_WITH_NULL_SHA ||
+ ssl->session_in->ciphersuite == TLS_RSA_WITH_NULL_SHA256 )
+ {
+ } else
+#endif
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+ else if( ssl->transform_in->ivlen == 12 )
+ {
+ unsigned char *dec_msg;
+ unsigned char *dec_msg_result;
+ size_t dec_msglen;
+ unsigned char add_data[13];
+ int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+
+#if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C)
+ if( ssl->session_in->ciphersuite == TLS_RSA_WITH_AES_128_GCM_SHA256 ||
+ ssl->session_in->ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 ||
+ ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ||
+ ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+ {
+ dec_msglen = ssl->in_msglen - ( ssl->transform_in->ivlen -
+ ssl->transform_in->fixed_ivlen );
+ dec_msglen -= 16;
+ dec_msg = ssl->in_msg + ( ssl->transform_in->ivlen -
+ ssl->transform_in->fixed_ivlen );
+ dec_msg_result = ssl->in_msg;
+ ssl->in_msglen = dec_msglen;
+
+ memcpy( add_data, ssl->in_ctr, 8 );
+ add_data[8] = ssl->in_msgtype;
+ add_data[9] = ssl->major_ver;
+ add_data[10] = ssl->minor_ver;
+ add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF;
+ add_data[12] = ssl->in_msglen & 0xFF;
+
+ SSL_DEBUG_BUF( 4, "additional data used for AEAD",
+ add_data, 13 );
+
+ memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen,
+ ssl->in_msg,
+ ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen );
+
+ SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec,
+ ssl->transform_in->ivlen );
+ SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, 16 );
+
+ memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen,
+ ssl->in_msg,
+ ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen );
+
+ ret = gcm_auth_decrypt( (gcm_context *) ssl->transform_in->ctx_dec,
+ dec_msglen,
+ ssl->transform_in->iv_dec,
+ ssl->transform_in->ivlen,
+ add_data, 13,
+ dec_msg + dec_msglen, 16,
+ dec_msg, dec_msg_result );
+
+ if( ret != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "AEAD decrypt failed on validation (ret = -0x%02x)",
+ -ret ) );
+
+ return( POLARSSL_ERR_SSL_INVALID_MAC );
+ }
+ } else
+#endif
+ return( ret );
+ }
+ else
+ {
+ /*
+ * Decrypt and check the padding
+ */
+ unsigned char *dec_msg;
+ unsigned char *dec_msg_result;
+ size_t dec_msglen;
+ size_t minlen = 0;
+
+ /*
+ * Check immediate ciphertext sanity
+ */
+ if( ssl->in_msglen % ssl->transform_in->ivlen != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0",
+ ssl->in_msglen, ssl->transform_in->ivlen ) );
+ return( POLARSSL_ERR_SSL_INVALID_MAC );
+ }
+
+ if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
+ minlen += ssl->transform_in->ivlen;
+
+ if( ssl->in_msglen < minlen + ssl->transform_in->ivlen ||
+ ssl->in_msglen < minlen + ssl->transform_in->maclen + 1 )
+ {
+ SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) + 1 ) ( + expl IV )",
+ ssl->in_msglen, ssl->transform_in->ivlen, ssl->transform_in->maclen ) );
+ return( POLARSSL_ERR_SSL_INVALID_MAC );
+ }
+
+ dec_msglen = ssl->in_msglen;
+ dec_msg = ssl->in_msg;
+ dec_msg_result = ssl->in_msg;
+
+ /*
+ * Initialize for prepended IV for block cipher in TLS v1.1 and up
+ */
+ if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
+ {
+ dec_msg += ssl->transform_in->ivlen;
+ dec_msglen -= ssl->transform_in->ivlen;
+ ssl->in_msglen -= ssl->transform_in->ivlen;
+
+ for( i = 0; i < ssl->transform_in->ivlen; i++ )
+ ssl->transform_in->iv_dec[i] = ssl->in_msg[i];
+ }
+
+ switch( ssl->transform_in->ivlen )
+ {
+#if defined(POLARSSL_DES_C)
+ case 8:
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+ if( ssl->session_in->ciphersuite == TLS_RSA_WITH_DES_CBC_SHA ||
+ ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_DES_CBC_SHA )
+ {
+ des_crypt_cbc( (des_context *) ssl->transform_in->ctx_dec,
+ DES_DECRYPT, dec_msglen,
+ ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
+ }
+ else
+#endif
+ des3_crypt_cbc( (des3_context *) ssl->transform_in->ctx_dec,
+ DES_DECRYPT, dec_msglen,
+ ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
+ break;
+#endif
+
+ case 16:
+#if defined(POLARSSL_AES_C)
+ if ( ssl->session_in->ciphersuite == TLS_RSA_WITH_AES_128_CBC_SHA ||
+ ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA ||
+ ssl->session_in->ciphersuite == TLS_RSA_WITH_AES_256_CBC_SHA ||
+ ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA ||
+ ssl->session_in->ciphersuite == TLS_RSA_WITH_AES_128_CBC_SHA256 ||
+ ssl->session_in->ciphersuite == TLS_RSA_WITH_AES_256_CBC_SHA256 ||
+ ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 ||
+ ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 )
+ {
+ aes_crypt_cbc( (aes_context *) ssl->transform_in->ctx_dec,
+ AES_DECRYPT, dec_msglen,
+ ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
+ break;
+ }
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+ if ( ssl->session_in->ciphersuite == TLS_RSA_WITH_CAMELLIA_128_CBC_SHA ||
+ ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA ||
+ ssl->session_in->ciphersuite == TLS_RSA_WITH_CAMELLIA_256_CBC_SHA ||
+ ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA ||
+ ssl->session_in->ciphersuite == TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 ||
+ ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 ||
+ ssl->session_in->ciphersuite == TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 ||
+ ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 )
+ {
+ camellia_crypt_cbc( (camellia_context *) ssl->transform_in->ctx_dec,
+ CAMELLIA_DECRYPT, dec_msglen,
+ ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
+ break;
+ }
+#endif
+
+ default:
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+
+ padlen = 1 + ssl->in_msg[ssl->in_msglen - 1];
+
+ if( ssl->in_msglen < ssl->transform_in->maclen + padlen )
+ {
+#if defined(POLARSSL_SSL_DEBUG_ALL)
+ SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)",
+ ssl->in_msglen, ssl->transform_in->maclen, padlen ) );
+#endif
+ padlen = 0;
+ correct = 0;
+ }
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ if( padlen > ssl->transform_in->ivlen )
+ {
+#if defined(POLARSSL_SSL_DEBUG_ALL)
+ SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, "
+ "should be no more than %d",
+ padlen, ssl->transform_in->ivlen ) );
+#endif
+ correct = 0;
+ }
+ }
+ else
+ {
+ /*
+ * TLSv1+: always check the padding up to the first failure
+ * and fake check up to 256 bytes of padding
+ */
+ size_t pad_count = 0, fake_pad_count = 0;
+ size_t padding_idx = ssl->in_msglen - padlen - 1;
+
+ for( i = 1; i <= padlen; i++ )
+ pad_count += ( ssl->in_msg[padding_idx + i] == padlen - 1 );
+
+ for( ; i <= 256; i++ )
+ fake_pad_count += ( ssl->in_msg[padding_idx + i] == padlen - 1 );
+
+ correct &= ( pad_count == padlen ); /* Only 1 on correct padding */
+ correct &= ( pad_count + fake_pad_count < 512 ); /* Always 1 */
+
+#if defined(POLARSSL_SSL_DEBUG_ALL)
+ if( padlen > 0 && correct == 0)
+ SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) );
+#endif
+ padlen &= correct * 0x1FF;
+ }
+ }
+
+ SSL_DEBUG_BUF( 4, "raw buffer after decryption",
+ ssl->in_msg, ssl->in_msglen );
+
+ /*
+ * Always compute the MAC (RFC4346, CBCTIME).
+ */
+ ssl->in_msglen -= ( ssl->transform_in->maclen + padlen );
+
+ ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 );
+ ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen );
+
+ memcpy( tmp, ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen );
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ if( ssl->transform_in->maclen == 16 )
+ ssl_mac_md5( ssl->transform_in->mac_dec,
+ ssl->in_msg, ssl->in_msglen,
+ ssl->in_ctr, ssl->in_msgtype );
+ else if( ssl->transform_in->maclen == 20 )
+ ssl_mac_sha1( ssl->transform_in->mac_dec,
+ ssl->in_msg, ssl->in_msglen,
+ ssl->in_ctr, ssl->in_msgtype );
+ else if( ssl->transform_in->maclen == 32 )
+ ssl_mac_sha2( ssl->transform_in->mac_dec,
+ ssl->in_msg, ssl->in_msglen,
+ ssl->in_ctr, ssl->in_msgtype );
+ else if( ssl->transform_in->maclen != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d",
+ ssl->transform_in->maclen ) );
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+ }
+ else
+ {
+ /*
+ * Process MAC and always update for padlen afterwards to make
+ * total time independent of padlen
+ *
+ * extra_run compensates MAC check for padlen
+ *
+ * Known timing attacks:
+ * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf)
+ *
+ * We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values
+ * correctly. (We round down instead of up, so -56 is the correct
+ * value for our calculations instead of -55)
+ */
+ int j, extra_run = 0;
+ extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 -
+ ( 13 + ssl->in_msglen + 8 ) / 64;
+
+ extra_run &= correct * 0xFF;
+
+ if( ssl->transform_in->maclen == 16 )
+ {
+ md5_context ctx;
+ md5_hmac_starts( &ctx, ssl->transform_in->mac_dec, 16 );
+ md5_hmac_update( &ctx, ssl->in_ctr, ssl->in_msglen + 13 );
+ md5_hmac_finish( &ctx, ssl->in_msg + ssl->in_msglen );
+
+ for( j = 0; j < extra_run; j++ )
+ md5_process( &ctx, ssl->in_msg );
+ }
+ else if( ssl->transform_in->maclen == 20 )
+ {
+ sha1_context ctx;
+ sha1_hmac_starts( &ctx, ssl->transform_in->mac_dec, 20 );
+ sha1_hmac_update( &ctx, ssl->in_ctr, ssl->in_msglen + 13 );
+ sha1_hmac_finish( &ctx, ssl->in_msg + ssl->in_msglen );
+
+ for( j = 0; j < extra_run; j++ )
+ sha1_process( &ctx, ssl->in_msg );
+ }
+ else if( ssl->transform_in->maclen == 32 )
+ {
+ sha2_context ctx;
+ sha2_hmac_starts( &ctx, ssl->transform_in->mac_dec, 32, 0 );
+ sha2_hmac_update( &ctx, ssl->in_ctr, ssl->in_msglen + 13 );
+ sha2_hmac_finish( &ctx, ssl->in_msg + ssl->in_msglen );
+
+ for( j = 0; j < extra_run; j++ )
+ sha2_process( &ctx, ssl->in_msg );
+ }
+ else if( ssl->transform_in->maclen != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d",
+ ssl->transform_in->maclen ) );
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+ }
+
+ SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->transform_in->maclen );
+ SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen,
+ ssl->transform_in->maclen );
+
+ if( memcmp( tmp, ssl->in_msg + ssl->in_msglen,
+ ssl->transform_in->maclen ) != 0 )
+ {
+#if defined(POLARSSL_SSL_DEBUG_ALL)
+ SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
+#endif
+ correct = 0;
+ }
+
+ /*
+ * Finally check the correct flag
+ */
+ if( correct == 0 )
+ return( POLARSSL_ERR_SSL_INVALID_MAC );
+
+ if( ssl->in_msglen == 0 )
+ {
+ ssl->nb_zero++;
+
+ /*
+ * Three or more empty messages may be a DoS attack
+ * (excessive CPU consumption).
+ */
+ if( ssl->nb_zero > 3 )
+ {
+ SSL_DEBUG_MSG( 1, ( "received four consecutive empty "
+ "messages, possible DoS attack" ) );
+ return( POLARSSL_ERR_SSL_INVALID_MAC );
+ }
+ }
+ else
+ ssl->nb_zero = 0;
+
+ for( i = 8; i > 0; i-- )
+ if( ++ssl->in_ctr[i - 1] != 0 )
+ break;
+
+ SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) );
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+/*
+ * Compression/decompression functions
+ */
+static int ssl_compress_buf( ssl_context *ssl )
+{
+ int ret;
+ unsigned char *msg_post = ssl->out_msg;
+ size_t len_pre = ssl->out_msglen;
+ unsigned char *msg_pre;
+
+ SSL_DEBUG_MSG( 2, ( "=> compress buf" ) );
+
+ msg_pre = (unsigned char*) malloc( len_pre );
+ if( msg_pre == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len_pre ) );
+ return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+ }
+
+ memcpy( msg_pre, ssl->out_msg, len_pre );
+
+ SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ",
+ ssl->out_msglen ) );
+
+ SSL_DEBUG_BUF( 4, "before compression: output payload",
+ ssl->out_msg, ssl->out_msglen );
+
+ ssl->transform_out->ctx_deflate.next_in = msg_pre;
+ ssl->transform_out->ctx_deflate.avail_in = len_pre;
+ ssl->transform_out->ctx_deflate.next_out = msg_post;
+ ssl->transform_out->ctx_deflate.avail_out = SSL_BUFFER_LEN;
+
+ ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH );
+ if( ret != Z_OK )
+ {
+ SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) );
+ return( POLARSSL_ERR_SSL_COMPRESSION_FAILED );
+ }
+
+ ssl->out_msglen = SSL_BUFFER_LEN - ssl->transform_out->ctx_deflate.avail_out;
+
+ free( msg_pre );
+
+ SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ",
+ ssl->out_msglen ) );
+
+ SSL_DEBUG_BUF( 4, "after compression: output payload",
+ ssl->out_msg, ssl->out_msglen );
+
+ SSL_DEBUG_MSG( 2, ( "<= compress buf" ) );
+
+ return( 0 );
+}
+
+static int ssl_decompress_buf( ssl_context *ssl )
+{
+ int ret;
+ unsigned char *msg_post = ssl->in_msg;
+ size_t len_pre = ssl->in_msglen;
+ unsigned char *msg_pre;
+
+ SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) );
+
+ msg_pre = (unsigned char*) malloc( len_pre );
+ if( msg_pre == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len_pre ) );
+ return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+ }
+
+ memcpy( msg_pre, ssl->in_msg, len_pre );
+
+ SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ",
+ ssl->in_msglen ) );
+
+ SSL_DEBUG_BUF( 4, "before decompression: input payload",
+ ssl->in_msg, ssl->in_msglen );
+
+ ssl->transform_in->ctx_inflate.next_in = msg_pre;
+ ssl->transform_in->ctx_inflate.avail_in = len_pre;
+ ssl->transform_in->ctx_inflate.next_out = msg_post;
+ ssl->transform_in->ctx_inflate.avail_out = SSL_MAX_CONTENT_LEN;
+
+ ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH );
+ if( ret != Z_OK )
+ {
+ SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) );
+ return( POLARSSL_ERR_SSL_COMPRESSION_FAILED );
+ }
+
+ ssl->in_msglen = SSL_MAX_CONTENT_LEN - ssl->transform_in->ctx_inflate.avail_out;
+
+ free( msg_pre );
+
+ SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ",
+ ssl->in_msglen ) );
+
+ SSL_DEBUG_BUF( 4, "after decompression: input payload",
+ ssl->in_msg, ssl->in_msglen );
+
+ SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) );
+
+ return( 0 );
+}
+#endif /* POLARSSL_ZLIB_SUPPORT */
+
+/*
+ * Fill the input message buffer
+ */
+int ssl_fetch_input( ssl_context *ssl, size_t nb_want )
+{
+ int ret;
+ size_t len;
+
+ SSL_DEBUG_MSG( 2, ( "=> fetch input" ) );
+
+ while( ssl->in_left < nb_want )
+ {
+ len = nb_want - ssl->in_left;
+ ret = ssl->f_recv( ssl->p_recv, ssl->in_hdr + ssl->in_left, len );
+
+ SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
+ ssl->in_left, nb_want ) );
+ SSL_DEBUG_RET( 2, "ssl->f_recv", ret );
+
+ if( ret == 0 )
+ return( POLARSSL_ERR_SSL_CONN_EOF );
+
+ if( ret < 0 )
+ return( ret );
+
+ ssl->in_left += ret;
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
+
+ return( 0 );
+}
+
+/*
+ * Flush any data not yet written
+ */
+int ssl_flush_output( ssl_context *ssl )
+{
+ int ret;
+ unsigned char *buf;
+
+ SSL_DEBUG_MSG( 2, ( "=> flush output" ) );
+
+ while( ssl->out_left > 0 )
+ {
+ SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d",
+ 5 + ssl->out_msglen, ssl->out_left ) );
+
+ if( ssl->out_msglen < ssl->out_left )
+ {
+ size_t header_left = ssl->out_left - ssl->out_msglen;
+
+ buf = ssl->out_hdr + 5 - header_left;
+ ret = ssl->f_send( ssl->p_send, buf, header_left );
+
+ SSL_DEBUG_RET( 2, "ssl->f_send (header)", ret );
+
+ if( ret <= 0 )
+ return( ret );
+
+ ssl->out_left -= ret;
+ }
+
+ buf = ssl->out_msg + ssl->out_msglen - ssl->out_left;
+ ret = ssl->f_send( ssl->p_send, buf, ssl->out_left );
+
+ SSL_DEBUG_RET( 2, "ssl->f_send", ret );
+
+ if( ret <= 0 )
+ return( ret );
+
+ ssl->out_left -= ret;
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
+
+ return( 0 );
+}
+
+/*
+ * Record layer functions
+ */
+int ssl_write_record( ssl_context *ssl )
+{
+ int ret, done = 0;
+ size_t len = ssl->out_msglen;
+
+ SSL_DEBUG_MSG( 2, ( "=> write record" ) );
+
+ if( ssl->out_msgtype == SSL_MSG_HANDSHAKE )
+ {
+ ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 );
+ ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 );
+ ssl->out_msg[3] = (unsigned char)( ( len - 4 ) );
+
+ ssl->handshake->update_checksum( ssl, ssl->out_msg, len );
+ }
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+ if( ssl->transform_out != NULL &&
+ ssl->session_out->compression == SSL_COMPRESS_DEFLATE )
+ {
+ if( ( ret = ssl_compress_buf( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_compress_buf", ret );
+ return( ret );
+ }
+
+ len = ssl->out_msglen;
+ }
+#endif /*POLARSSL_ZLIB_SUPPORT */
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+ if( ssl_hw_record_write != NULL)
+ {
+ SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_write()" ) );
+
+ ret = ssl_hw_record_write( ssl );
+ if( ret != 0 && ret != POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH )
+ {
+ SSL_DEBUG_RET( 1, "ssl_hw_record_write", ret );
+ return POLARSSL_ERR_SSL_HW_ACCEL_FAILED;
+ }
+ done = 1;
+ }
+#endif
+ if( !done )
+ {
+ ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
+ ssl->out_hdr[1] = (unsigned char) ssl->major_ver;
+ ssl->out_hdr[2] = (unsigned char) ssl->minor_ver;
+ ssl->out_hdr[3] = (unsigned char)( len >> 8 );
+ ssl->out_hdr[4] = (unsigned char)( len );
+
+ if( ssl->transform_out != NULL )
+ {
+ if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret );
+ return( ret );
+ }
+
+ len = ssl->out_msglen;
+ ssl->out_hdr[3] = (unsigned char)( len >> 8 );
+ ssl->out_hdr[4] = (unsigned char)( len );
+ }
+
+ ssl->out_left = 5 + ssl->out_msglen;
+
+ SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, "
+ "version = [%d:%d], msglen = %d",
+ ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2],
+ ( ssl->out_hdr[3] << 8 ) | ssl->out_hdr[4] ) );
+
+ SSL_DEBUG_BUF( 4, "output record header sent to network",
+ ssl->out_hdr, 5 );
+ SSL_DEBUG_BUF( 4, "output record sent to network",
+ ssl->out_hdr + 32, ssl->out_msglen );
+ }
+
+ if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write record" ) );
+
+ return( 0 );
+}
+
+int ssl_read_record( ssl_context *ssl )
+{
+ int ret, done = 0;
+
+ SSL_DEBUG_MSG( 2, ( "=> read record" ) );
+
+ if( ssl->in_hslen != 0 &&
+ ssl->in_hslen < ssl->in_msglen )
+ {
+ /*
+ * Get next Handshake message in the current record
+ */
+ ssl->in_msglen -= ssl->in_hslen;
+
+ memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen,
+ ssl->in_msglen );
+
+ ssl->in_hslen = 4;
+ ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3];
+
+ SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
+ " %d, type = %d, hslen = %d",
+ ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
+
+ if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->in_msglen < ssl->in_hslen )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
+
+ return( 0 );
+ }
+
+ ssl->in_hslen = 0;
+
+ /*
+ * Read the record header and validate it
+ */
+ if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+ return( ret );
+ }
+
+ ssl->in_msgtype = ssl->in_hdr[0];
+ ssl->in_msglen = ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4];
+
+ SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, "
+ "version = [%d:%d], msglen = %d",
+ ssl->in_hdr[0], ssl->in_hdr[1], ssl->in_hdr[2],
+ ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4] ) );
+
+ if( ssl->in_hdr[1] != ssl->major_ver )
+ {
+ SSL_DEBUG_MSG( 1, ( "major version mismatch" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->in_hdr[2] > ssl->max_minor_ver )
+ {
+ SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ /*
+ * Make sure the message length is acceptable
+ */
+ if( ssl->transform_in == NULL )
+ {
+ if( ssl->in_msglen < 1 ||
+ ssl->in_msglen > SSL_MAX_CONTENT_LEN )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+ }
+ else
+ {
+ if( ssl->in_msglen < ssl->transform_in->minlen )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_0 &&
+ ssl->in_msglen > ssl->transform_in->minlen + SSL_MAX_CONTENT_LEN )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ /*
+ * TLS encrypted messages can have up to 256 bytes of padding
+ */
+ if( ssl->minor_ver >= SSL_MINOR_VERSION_1 &&
+ ssl->in_msglen > ssl->transform_in->minlen + SSL_MAX_CONTENT_LEN + 256 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+ }
+
+ /*
+ * Read and optionally decrypt the message contents
+ */
+ if( ( ret = ssl_fetch_input( ssl, 5 + ssl->in_msglen ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_BUF( 4, "input record from network",
+ ssl->in_hdr, 5 + ssl->in_msglen );
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+ if( ssl_hw_record_read != NULL)
+ {
+ SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_read()" ) );
+
+ ret = ssl_hw_record_read( ssl );
+ if( ret != 0 && ret != POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH )
+ {
+ SSL_DEBUG_RET( 1, "ssl_hw_record_read", ret );
+ return POLARSSL_ERR_SSL_HW_ACCEL_FAILED;
+ }
+ done = 1;
+ }
+#endif
+ if( !done && ssl->transform_in != NULL )
+ {
+ if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 )
+ {
+#if defined(POLARSSL_SSL_ALERT_MESSAGES)
+ if( ret == POLARSSL_ERR_SSL_INVALID_MAC )
+ {
+ ssl_send_alert_message( ssl,
+ SSL_ALERT_LEVEL_FATAL,
+ SSL_ALERT_MSG_BAD_RECORD_MAC );
+ }
+#endif
+ SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_BUF( 4, "input payload after decrypt",
+ ssl->in_msg, ssl->in_msglen );
+
+ if( ssl->in_msglen > SSL_MAX_CONTENT_LEN )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+ }
+
+#if defined(POLARSSL_ZLIB_SUPPORT)
+ if( ssl->transform_in != NULL &&
+ ssl->session_in->compression == SSL_COMPRESS_DEFLATE )
+ {
+ if( ( ret = ssl_decompress_buf( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret );
+ return( ret );
+ }
+
+ ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 );
+ ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen );
+ }
+#endif /* POLARSSL_ZLIB_SUPPORT */
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE &&
+ ssl->in_msgtype != SSL_MSG_ALERT &&
+ ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC &&
+ ssl->in_msgtype != SSL_MSG_APPLICATION_DATA )
+ {
+ SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
+
+ if( ( ret = ssl_send_alert_message( ssl,
+ SSL_ALERT_LEVEL_FATAL,
+ SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->in_msgtype == SSL_MSG_HANDSHAKE )
+ {
+ ssl->in_hslen = 4;
+ ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3];
+
+ SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
+ " %d, type = %d, hslen = %d",
+ ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
+
+ /*
+ * Additional checks to validate the handshake header
+ */
+ if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->in_msglen < ssl->in_hslen )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->state != SSL_HANDSHAKE_OVER )
+ ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
+ }
+
+ if( ssl->in_msgtype == SSL_MSG_ALERT )
+ {
+ SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]",
+ ssl->in_msg[0], ssl->in_msg[1] ) );
+
+ /*
+ * Ignore non-fatal alerts, except close_notify
+ */
+ if( ssl->in_msg[0] == SSL_ALERT_LEVEL_FATAL )
+ {
+ SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)",
+ ssl->in_msg[1] ) );
+ /**
+ * Subtract from error code as ssl->in_msg[1] is 7-bit positive
+ * error identifier.
+ */
+ return( POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE );
+ }
+
+ if( ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING &&
+ ssl->in_msg[1] == SSL_ALERT_MSG_CLOSE_NOTIFY )
+ {
+ SSL_DEBUG_MSG( 2, ( "is a close notify message" ) );
+ return( POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY );
+ }
+ }
+
+ ssl->in_left = 0;
+
+ SSL_DEBUG_MSG( 2, ( "<= read record" ) );
+
+ return( 0 );
+}
+
+int ssl_send_fatal_handshake_failure( ssl_context *ssl )
+{
+ int ret;
+
+ if( ( ret = ssl_send_alert_message( ssl,
+ SSL_ALERT_LEVEL_FATAL,
+ SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ return( 0 );
+}
+
+int ssl_send_alert_message( ssl_context *ssl,
+ unsigned char level,
+ unsigned char message )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> send alert message" ) );
+
+ ssl->out_msgtype = SSL_MSG_ALERT;
+ ssl->out_msglen = 2;
+ ssl->out_msg[0] = level;
+ ssl->out_msg[1] = message;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= send alert message" ) );
+
+ return( 0 );
+}
+
+/*
+ * Handshake functions
+ */
+int ssl_write_certificate( ssl_context *ssl )
+{
+ int ret;
+ size_t i, n;
+ const x509_cert *crt;
+
+ SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
+
+ if( ssl->endpoint == SSL_IS_CLIENT )
+ {
+ if( ssl->client_auth == 0 )
+ {
+ SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+ /*
+ * If using SSLv3 and got no cert, send an Alert message
+ * (otherwise an empty Certificate message will be sent).
+ */
+ if( ssl->own_cert == NULL &&
+ ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ ssl->out_msglen = 2;
+ ssl->out_msgtype = SSL_MSG_ALERT;
+ ssl->out_msg[0] = SSL_ALERT_LEVEL_WARNING;
+ ssl->out_msg[1] = SSL_ALERT_MSG_NO_CERT;
+
+ SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) );
+ goto write_msg;
+ }
+ }
+ else /* SSL_IS_SERVER */
+ {
+ if( ssl->own_cert == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) );
+ return( POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED );
+ }
+ }
+
+ SSL_DEBUG_CRT( 3, "own certificate", ssl->own_cert );
+
+ /*
+ * 0 . 0 handshake type
+ * 1 . 3 handshake length
+ * 4 . 6 length of all certs
+ * 7 . 9 length of cert. 1
+ * 10 . n-1 peer certificate
+ * n . n+2 length of cert. 2
+ * n+3 . ... upper level cert, etc.
+ */
+ i = 7;
+ crt = ssl->own_cert;
+
+ while( crt != NULL )
+ {
+ n = crt->raw.len;
+ if( i + 3 + n > SSL_MAX_CONTENT_LEN )
+ {
+ SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d",
+ i + 3 + n, SSL_MAX_CONTENT_LEN ) );
+ return( POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE );
+ }
+
+ ssl->out_msg[i ] = (unsigned char)( n >> 16 );
+ ssl->out_msg[i + 1] = (unsigned char)( n >> 8 );
+ ssl->out_msg[i + 2] = (unsigned char)( n );
+
+ i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n );
+ i += n; crt = crt->next;
+ }
+
+ ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 );
+ ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 );
+ ssl->out_msg[6] = (unsigned char)( ( i - 7 ) );
+
+ ssl->out_msglen = i;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_CERTIFICATE;
+
+write_msg:
+
+ ssl->state++;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write certificate" ) );
+
+ return( 0 );
+}
+
+int ssl_parse_certificate( ssl_context *ssl )
+{
+ int ret;
+ size_t i, n;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
+
+ if( ssl->endpoint == SSL_IS_SERVER &&
+ ssl->authmode == SSL_VERIFY_NONE )
+ {
+ ssl->verify_result = BADCERT_SKIP_VERIFY;
+ SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ ssl->state++;
+
+ /*
+ * Check if the client sent an empty certificate
+ */
+ if( ssl->endpoint == SSL_IS_SERVER &&
+ ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ if( ssl->in_msglen == 2 &&
+ ssl->in_msgtype == SSL_MSG_ALERT &&
+ ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING &&
+ ssl->in_msg[1] == SSL_ALERT_MSG_NO_CERT )
+ {
+ SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) );
+
+ ssl->verify_result = BADCERT_MISSING;
+ if( ssl->authmode == SSL_VERIFY_OPTIONAL )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE );
+ }
+ }
+
+ if( ssl->endpoint == SSL_IS_SERVER &&
+ ssl->minor_ver != SSL_MINOR_VERSION_0 )
+ {
+ if( ssl->in_hslen == 7 &&
+ ssl->in_msgtype == SSL_MSG_HANDSHAKE &&
+ ssl->in_msg[0] == SSL_HS_CERTIFICATE &&
+ memcmp( ssl->in_msg + 4, "\0\0\0", 3 ) == 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) );
+
+ ssl->verify_result = BADCERT_MISSING;
+ if( ssl->authmode == SSL_VERIFY_REQUIRED )
+ return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE );
+ else
+ return( 0 );
+ }
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ if( ssl->in_msg[0] != SSL_HS_CERTIFICATE || ssl->in_hslen < 10 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+ }
+
+ /*
+ * Same message structure as in ssl_write_certificate()
+ */
+ n = ( ssl->in_msg[5] << 8 ) | ssl->in_msg[6];
+
+ if( ssl->in_msg[4] != 0 || ssl->in_hslen != 7 + n )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+ }
+
+ if( ( ssl->session_negotiate->peer_cert = (x509_cert *) malloc(
+ sizeof( x509_cert ) ) ) == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed",
+ sizeof( x509_cert ) ) );
+ return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+ }
+
+ memset( ssl->session_negotiate->peer_cert, 0, sizeof( x509_cert ) );
+
+ i = 7;
+
+ while( i < ssl->in_hslen )
+ {
+ if( ssl->in_msg[i] != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+ }
+
+ n = ( (unsigned int) ssl->in_msg[i + 1] << 8 )
+ | (unsigned int) ssl->in_msg[i + 2];
+ i += 3;
+
+ if( n < 128 || i + n > ssl->in_hslen )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+ }
+
+ ret = x509parse_crt_der( ssl->session_negotiate->peer_cert,
+ ssl->in_msg + i, n );
+ if( ret != 0 )
+ {
+ SSL_DEBUG_RET( 1, " x509parse_crt", ret );
+ return( ret );
+ }
+
+ i += n;
+ }
+
+ SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert );
+
+ if( ssl->authmode != SSL_VERIFY_NONE )
+ {
+ if( ssl->ca_chain == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
+ return( POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED );
+ }
+
+ ret = x509parse_verify( ssl->session_negotiate->peer_cert,
+ ssl->ca_chain, ssl->ca_crl,
+ ssl->peer_cn, &ssl->verify_result,
+ ssl->f_vrfy, ssl->p_vrfy );
+
+ if( ret != 0 )
+ SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
+
+ if( ssl->authmode != SSL_VERIFY_REQUIRED )
+ ret = 0;
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
+
+ return( ret );
+}
+
+int ssl_write_change_cipher_spec( ssl_context *ssl )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) );
+
+ ssl->out_msgtype = SSL_MSG_CHANGE_CIPHER_SPEC;
+ ssl->out_msglen = 1;
+ ssl->out_msg[0] = 1;
+
+ ssl->state++;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) );
+
+ return( 0 );
+}
+
+int ssl_parse_change_cipher_spec( ssl_context *ssl )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
+
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC );
+ }
+
+ ssl->state++;
+
+ SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) );
+
+ return( 0 );
+}
+
+void ssl_optimize_checksum( ssl_context *ssl, int ciphersuite )
+{
+#if !defined(POLARSSL_SHA4_C)
+ ((void) ciphersuite);
+#endif
+
+ if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
+ ssl->handshake->update_checksum = ssl_update_checksum_md5sha1;
+#if defined(POLARSSL_SHA4_C)
+ else if ( ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 ||
+ ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+ {
+ ssl->handshake->update_checksum = ssl_update_checksum_sha384;
+ }
+#endif
+ else
+ ssl->handshake->update_checksum = ssl_update_checksum_sha256;
+}
+
+static void ssl_update_checksum_start( ssl_context *ssl, unsigned char *buf,
+ size_t len )
+{
+ md5_update( &ssl->handshake->fin_md5 , buf, len );
+ sha1_update( &ssl->handshake->fin_sha1, buf, len );
+ sha2_update( &ssl->handshake->fin_sha2, buf, len );
+#if defined(POLARSSL_SHA4_C)
+ sha4_update( &ssl->handshake->fin_sha4, buf, len );
+#endif
+}
+
+static void ssl_update_checksum_md5sha1( ssl_context *ssl, unsigned char *buf,
+ size_t len )
+{
+ md5_update( &ssl->handshake->fin_md5 , buf, len );
+ sha1_update( &ssl->handshake->fin_sha1, buf, len );
+}
+
+static void ssl_update_checksum_sha256( ssl_context *ssl, unsigned char *buf,
+ size_t len )
+{
+ sha2_update( &ssl->handshake->fin_sha2, buf, len );
+}
+
+#if defined(POLARSSL_SHA4_C)
+static void ssl_update_checksum_sha384( ssl_context *ssl, unsigned char *buf,
+ size_t len )
+{
+ sha4_update( &ssl->handshake->fin_sha4, buf, len );
+}
+#endif
+
+static void ssl_calc_finished_ssl(
+ ssl_context *ssl, unsigned char *buf, int from )
+{
+ const char *sender;
+ md5_context md5;
+ sha1_context sha1;
+
+ unsigned char padbuf[48];
+ unsigned char md5sum[16];
+ unsigned char sha1sum[20];
+
+ ssl_session *session = ssl->session_negotiate;
+ if( !session )
+ session = ssl->session;
+
+ SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) );
+
+ memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) );
+ memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) );
+
+ /*
+ * SSLv3:
+ * hash =
+ * MD5( master + pad2 +
+ * MD5( handshake + sender + master + pad1 ) )
+ * + SHA1( master + pad2 +
+ * SHA1( handshake + sender + master + pad1 ) )
+ */
+
+#if !defined(POLARSSL_MD5_ALT)
+ SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *)
+ md5.state, sizeof( md5.state ) );
+#endif
+
+#if !defined(POLARSSL_SHA1_ALT)
+ SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *)
+ sha1.state, sizeof( sha1.state ) );
+#endif
+
+ sender = ( from == SSL_IS_CLIENT ) ? "CLNT"
+ : "SRVR";
+
+ memset( padbuf, 0x36, 48 );
+
+ md5_update( &md5, (const unsigned char *) sender, 4 );
+ md5_update( &md5, session->master, 48 );
+ md5_update( &md5, padbuf, 48 );
+ md5_finish( &md5, md5sum );
+
+ sha1_update( &sha1, (const unsigned char *) sender, 4 );
+ sha1_update( &sha1, session->master, 48 );
+ sha1_update( &sha1, padbuf, 40 );
+ sha1_finish( &sha1, sha1sum );
+
+ memset( padbuf, 0x5C, 48 );
+
+ md5_starts( &md5 );
+ md5_update( &md5, session->master, 48 );
+ md5_update( &md5, padbuf, 48 );
+ md5_update( &md5, md5sum, 16 );
+ md5_finish( &md5, buf );
+
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, session->master, 48 );
+ sha1_update( &sha1, padbuf , 40 );
+ sha1_update( &sha1, sha1sum, 20 );
+ sha1_finish( &sha1, buf + 16 );
+
+ SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 );
+
+ memset( &md5, 0, sizeof( md5_context ) );
+ memset( &sha1, 0, sizeof( sha1_context ) );
+
+ memset( padbuf, 0, sizeof( padbuf ) );
+ memset( md5sum, 0, sizeof( md5sum ) );
+ memset( sha1sum, 0, sizeof( sha1sum ) );
+
+ SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
+}
+
+static void ssl_calc_finished_tls(
+ ssl_context *ssl, unsigned char *buf, int from )
+{
+ int len = 12;
+ const char *sender;
+ md5_context md5;
+ sha1_context sha1;
+ unsigned char padbuf[36];
+
+ ssl_session *session = ssl->session_negotiate;
+ if( !session )
+ session = ssl->session;
+
+ SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) );
+
+ memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) );
+ memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) );
+
+ /*
+ * TLSv1:
+ * hash = PRF( master, finished_label,
+ * MD5( handshake ) + SHA1( handshake ) )[0..11]
+ */
+
+#if !defined(POLARSSL_MD5_ALT)
+ SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *)
+ md5.state, sizeof( md5.state ) );
+#endif
+
+#if !defined(POLARSSL_SHA1_ALT)
+ SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *)
+ sha1.state, sizeof( sha1.state ) );
+#endif
+
+ sender = ( from == SSL_IS_CLIENT )
+ ? "client finished"
+ : "server finished";
+
+ md5_finish( &md5, padbuf );
+ sha1_finish( &sha1, padbuf + 16 );
+
+ ssl->handshake->tls_prf( session->master, 48, (char *) sender,
+ padbuf, 36, buf, len );
+
+ SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
+
+ memset( &md5, 0, sizeof( md5_context ) );
+ memset( &sha1, 0, sizeof( sha1_context ) );
+
+ memset( padbuf, 0, sizeof( padbuf ) );
+
+ SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
+}
+
+static void ssl_calc_finished_tls_sha256(
+ ssl_context *ssl, unsigned char *buf, int from )
+{
+ int len = 12;
+ const char *sender;
+ sha2_context sha2;
+ unsigned char padbuf[32];
+
+ ssl_session *session = ssl->session_negotiate;
+ if( !session )
+ session = ssl->session;
+
+ SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) );
+
+ memcpy( &sha2, &ssl->handshake->fin_sha2, sizeof(sha2_context) );
+
+ /*
+ * TLSv1.2:
+ * hash = PRF( master, finished_label,
+ * Hash( handshake ) )[0.11]
+ */
+
+#if !defined(POLARSSL_SHA2_ALT)
+ SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *)
+ sha2.state, sizeof( sha2.state ) );
+#endif
+
+ sender = ( from == SSL_IS_CLIENT )
+ ? "client finished"
+ : "server finished";
+
+ sha2_finish( &sha2, padbuf );
+
+ ssl->handshake->tls_prf( session->master, 48, (char *) sender,
+ padbuf, 32, buf, len );
+
+ SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
+
+ memset( &sha2, 0, sizeof( sha2_context ) );
+
+ memset( padbuf, 0, sizeof( padbuf ) );
+
+ SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
+}
+
+#if defined(POLARSSL_SHA4_C)
+static void ssl_calc_finished_tls_sha384(
+ ssl_context *ssl, unsigned char *buf, int from )
+{
+ int len = 12;
+ const char *sender;
+ sha4_context sha4;
+ unsigned char padbuf[48];
+
+ ssl_session *session = ssl->session_negotiate;
+ if( !session )
+ session = ssl->session;
+
+ SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) );
+
+ memcpy( &sha4, &ssl->handshake->fin_sha4, sizeof(sha4_context) );
+
+ /*
+ * TLSv1.2:
+ * hash = PRF( master, finished_label,
+ * Hash( handshake ) )[0.11]
+ */
+
+#if !defined(POLARSSL_SHA4_ALT)
+ SSL_DEBUG_BUF( 4, "finished sha4 state", (unsigned char *)
+ sha4.state, sizeof( sha4.state ) );
+#endif
+
+ sender = ( from == SSL_IS_CLIENT )
+ ? "client finished"
+ : "server finished";
+
+ sha4_finish( &sha4, padbuf );
+
+ ssl->handshake->tls_prf( session->master, 48, (char *) sender,
+ padbuf, 48, buf, len );
+
+ SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
+
+ memset( &sha4, 0, sizeof( sha4_context ) );
+
+ memset( padbuf, 0, sizeof( padbuf ) );
+
+ SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
+}
+#endif
+
+void ssl_handshake_wrapup( ssl_context *ssl )
+{
+ SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) );
+
+ /*
+ * Free our handshake params
+ */
+ ssl_handshake_free( ssl->handshake );
+ free( ssl->handshake );
+ ssl->handshake = NULL;
+
+ /*
+ * Switch in our now active transform context
+ */
+ if( ssl->transform )
+ {
+ ssl_transform_free( ssl->transform );
+ free( ssl->transform );
+ }
+ ssl->transform = ssl->transform_negotiate;
+ ssl->transform_negotiate = NULL;
+
+ if( ssl->session )
+ {
+ ssl_session_free( ssl->session );
+ free( ssl->session );
+ }
+ ssl->session = ssl->session_negotiate;
+ ssl->session_negotiate = NULL;
+
+ /*
+ * Add cache entry
+ */
+ if( ssl->f_set_cache != NULL )
+ if( ssl->f_set_cache( ssl->p_set_cache, ssl->session ) != 0 )
+ SSL_DEBUG_MSG( 1, ( "cache did not store session" ) );
+
+ ssl->state++;
+
+ SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) );
+}
+
+int ssl_write_finished( ssl_context *ssl )
+{
+ int ret, hash_len;
+
+ SSL_DEBUG_MSG( 2, ( "=> write finished" ) );
+
+ ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->endpoint );
+
+ // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63)
+ hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12;
+
+ ssl->verify_data_len = hash_len;
+ memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len );
+
+ ssl->out_msglen = 4 + hash_len;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_FINISHED;
+
+ /*
+ * In case of session resuming, invert the client and server
+ * ChangeCipherSpec messages order.
+ */
+ if( ssl->handshake->resume != 0 )
+ {
+ if( ssl->endpoint == SSL_IS_CLIENT )
+ ssl->state = SSL_HANDSHAKE_WRAPUP;
+ else
+ ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC;
+ }
+ else
+ ssl->state++;
+
+ /*
+ * Switch to our negotiated transform and session parameters for outbound data.
+ */
+ SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) );
+ ssl->transform_out = ssl->transform_negotiate;
+ ssl->session_out = ssl->session_negotiate;
+ memset( ssl->out_ctr, 0, 8 );
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write finished" ) );
+
+ return( 0 );
+}
+
+int ssl_parse_finished( ssl_context *ssl )
+{
+ int ret;
+ unsigned int hash_len;
+ unsigned char buf[36];
+
+ SSL_DEBUG_MSG( 2, ( "=> parse finished" ) );
+
+ ssl->handshake->calc_finished( ssl, buf, ssl->endpoint ^ 1 );
+
+ /*
+ * Switch to our negotiated transform and session parameters for inbound data.
+ */
+ SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) );
+ ssl->transform_in = ssl->transform_negotiate;
+ ssl->session_in = ssl->session_negotiate;
+ memset( ssl->in_ctr, 0, 8 );
+
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63)
+ hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12;
+
+ if( ssl->in_msg[0] != SSL_HS_FINISHED ||
+ ssl->in_hslen != 4 + hash_len )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_FINISHED );
+ }
+
+ if( memcmp( ssl->in_msg + 4, buf, hash_len ) != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_FINISHED );
+ }
+
+ ssl->verify_data_len = hash_len;
+ memcpy( ssl->peer_verify_data, buf, hash_len );
+
+ if( ssl->handshake->resume != 0 )
+ {
+ if( ssl->endpoint == SSL_IS_CLIENT )
+ ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC;
+
+ if( ssl->endpoint == SSL_IS_SERVER )
+ ssl->state = SSL_HANDSHAKE_WRAPUP;
+ }
+ else
+ ssl->state++;
+
+ SSL_DEBUG_MSG( 2, ( "<= parse finished" ) );
+
+ return( 0 );
+}
+
+int ssl_handshake_init( ssl_context *ssl )
+{
+ if( ssl->transform_negotiate )
+ ssl_transform_free( ssl->transform_negotiate );
+ else
+ ssl->transform_negotiate = malloc( sizeof(ssl_transform) );
+
+ if( ssl->session_negotiate )
+ ssl_session_free( ssl->session_negotiate );
+ else
+ ssl->session_negotiate = malloc( sizeof(ssl_session) );
+
+ if( ssl->handshake )
+ ssl_handshake_free( ssl->handshake );
+ else
+ ssl->handshake = malloc( sizeof(ssl_handshake_params) );
+
+ if( ssl->handshake == NULL ||
+ ssl->transform_negotiate == NULL ||
+ ssl->session_negotiate == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "malloc() of ssl sub-contexts failed" ) );
+ return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+ }
+
+ memset( ssl->handshake, 0, sizeof(ssl_handshake_params) );
+ memset( ssl->transform_negotiate, 0, sizeof(ssl_transform) );
+ memset( ssl->session_negotiate, 0, sizeof(ssl_session) );
+
+ md5_starts( &ssl->handshake->fin_md5 );
+ sha1_starts( &ssl->handshake->fin_sha1 );
+ sha2_starts( &ssl->handshake->fin_sha2, 0 );
+#if defined(POLARSSL_SHA4_C)
+ sha4_starts( &ssl->handshake->fin_sha4, 1 );
+#endif
+
+ ssl->handshake->update_checksum = ssl_update_checksum_start;
+ ssl->handshake->sig_alg = SSL_HASH_SHA1;
+
+ return( 0 );
+}
+
+/*
+ * Initialize an SSL context
+ */
+int ssl_init( ssl_context *ssl )
+{
+ int ret;
+ int len = SSL_BUFFER_LEN;
+
+ memset( ssl, 0, sizeof( ssl_context ) );
+
+ /*
+ * Sane defaults
+ */
+ ssl->rsa_decrypt = ssl_rsa_decrypt;
+ ssl->rsa_sign = ssl_rsa_sign;
+ ssl->rsa_key_len = ssl_rsa_key_len;
+
+ ssl->min_major_ver = SSL_MAJOR_VERSION_3;
+ ssl->min_minor_ver = SSL_MINOR_VERSION_0;
+
+ ssl->ciphersuites = malloc( sizeof(int *) * 4 );
+ ssl_set_ciphersuites( ssl, ssl_default_ciphersuites );
+
+#if defined(POLARSSL_DHM_C)
+ if( ( ret = mpi_read_string( &ssl->dhm_P, 16,
+ POLARSSL_DHM_RFC5114_MODP_1024_P) ) != 0 ||
+ ( ret = mpi_read_string( &ssl->dhm_G, 16,
+ POLARSSL_DHM_RFC5114_MODP_1024_G) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "mpi_read_string", ret );
+ return( ret );
+ }
+#endif
+
+ /*
+ * Prepare base structures
+ */
+ ssl->in_ctr = (unsigned char *) malloc( len );
+ ssl->in_hdr = ssl->in_ctr + 8;
+ ssl->in_msg = ssl->in_ctr + 13;
+
+ if( ssl->in_ctr == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) );
+ return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+ }
+
+ ssl->out_ctr = (unsigned char *) malloc( len );
+ ssl->out_hdr = ssl->out_ctr + 8;
+ ssl->out_msg = ssl->out_ctr + 40;
+
+ if( ssl->out_ctr == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) );
+ free( ssl-> in_ctr );
+ return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+ }
+
+ memset( ssl-> in_ctr, 0, SSL_BUFFER_LEN );
+ memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
+
+ ssl->hostname = NULL;
+ ssl->hostname_len = 0;
+
+ if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
+ return( ret );
+
+ return( 0 );
+}
+
+/*
+ * Reset an initialized and used SSL context for re-use while retaining
+ * all application-set variables, function pointers and data.
+ */
+int ssl_session_reset( ssl_context *ssl )
+{
+ int ret;
+
+ ssl->state = SSL_HELLO_REQUEST;
+ ssl->renegotiation = SSL_INITIAL_HANDSHAKE;
+ ssl->secure_renegotiation = SSL_LEGACY_RENEGOTIATION;
+
+ ssl->verify_data_len = 0;
+ memset( ssl->own_verify_data, 0, 36 );
+ memset( ssl->peer_verify_data, 0, 36 );
+
+ ssl->in_offt = NULL;
+
+ ssl->in_msgtype = 0;
+ ssl->in_msglen = 0;
+ ssl->in_left = 0;
+
+ ssl->in_hslen = 0;
+ ssl->nb_zero = 0;
+
+ ssl->out_msgtype = 0;
+ ssl->out_msglen = 0;
+ ssl->out_left = 0;
+
+ ssl->transform_in = NULL;
+ ssl->transform_out = NULL;
+
+ memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
+ memset( ssl->in_ctr, 0, SSL_BUFFER_LEN );
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+ if( ssl_hw_record_reset != NULL)
+ {
+ SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_reset()" ) );
+ if( ssl_hw_record_reset( ssl ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_hw_record_reset", ret );
+ return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED );
+ }
+ }
+#endif
+
+ if( ssl->transform )
+ {
+ ssl_transform_free( ssl->transform );
+ free( ssl->transform );
+ ssl->transform = NULL;
+ }
+
+ if( ssl->session )
+ {
+ ssl_session_free( ssl->session );
+ free( ssl->session );
+ ssl->session = NULL;
+ }
+
+ if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
+ return( ret );
+
+ return( 0 );
+}
+
+/*
+ * SSL set accessors
+ */
+void ssl_set_endpoint( ssl_context *ssl, int endpoint )
+{
+ ssl->endpoint = endpoint;
+}
+
+void ssl_set_authmode( ssl_context *ssl, int authmode )
+{
+ ssl->authmode = authmode;
+}
+
+void ssl_set_verify( ssl_context *ssl,
+ int (*f_vrfy)(void *, x509_cert *, int, int *),
+ void *p_vrfy )
+{
+ ssl->f_vrfy = f_vrfy;
+ ssl->p_vrfy = p_vrfy;
+}
+
+void ssl_set_rng( ssl_context *ssl,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ ssl->f_rng = f_rng;
+ ssl->p_rng = p_rng;
+}
+
+void ssl_set_dbg( ssl_context *ssl,
+ void (*f_dbg)(void *, int, const char *),
+ void *p_dbg )
+{
+ ssl->f_dbg = f_dbg;
+ ssl->p_dbg = p_dbg;
+}
+
+void ssl_set_bio( ssl_context *ssl,
+ int (*f_recv)(void *, unsigned char *, size_t), void *p_recv,
+ int (*f_send)(void *, const unsigned char *, size_t), void *p_send )
+{
+ ssl->f_recv = f_recv;
+ ssl->f_send = f_send;
+ ssl->p_recv = p_recv;
+ ssl->p_send = p_send;
+}
+
+void ssl_set_session_cache( ssl_context *ssl,
+ int (*f_get_cache)(void *, ssl_session *), void *p_get_cache,
+ int (*f_set_cache)(void *, const ssl_session *), void *p_set_cache )
+{
+ ssl->f_get_cache = f_get_cache;
+ ssl->p_get_cache = p_get_cache;
+ ssl->f_set_cache = f_set_cache;
+ ssl->p_set_cache = p_set_cache;
+}
+
+void ssl_set_session( ssl_context *ssl, const ssl_session *session )
+{
+ memcpy( ssl->session_negotiate, session, sizeof(ssl_session) );
+ ssl->handshake->resume = 1;
+}
+
+void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites )
+{
+ ssl->ciphersuites[SSL_MINOR_VERSION_0] = ciphersuites;
+ ssl->ciphersuites[SSL_MINOR_VERSION_1] = ciphersuites;
+ ssl->ciphersuites[SSL_MINOR_VERSION_2] = ciphersuites;
+ ssl->ciphersuites[SSL_MINOR_VERSION_3] = ciphersuites;
+}
+
+void ssl_set_ciphersuites_for_version( ssl_context *ssl, const int *ciphersuites,
+ int major, int minor )
+{
+ if( major != SSL_MAJOR_VERSION_3 )
+ return;
+
+ if( minor < SSL_MINOR_VERSION_0 || minor > SSL_MINOR_VERSION_3 )
+ return;
+
+ ssl->ciphersuites[minor] = ciphersuites;
+}
+
+void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain,
+ x509_crl *ca_crl, const char *peer_cn )
+{
+ ssl->ca_chain = ca_chain;
+ ssl->ca_crl = ca_crl;
+ ssl->peer_cn = peer_cn;
+}
+
+void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert,
+ rsa_context *rsa_key )
+{
+ ssl->own_cert = own_cert;
+ ssl->rsa_key = rsa_key;
+}
+
+void ssl_set_own_cert_alt( ssl_context *ssl, x509_cert *own_cert,
+ void *rsa_key,
+ rsa_decrypt_func rsa_decrypt,
+ rsa_sign_func rsa_sign,
+ rsa_key_len_func rsa_key_len )
+{
+ ssl->own_cert = own_cert;
+ ssl->rsa_key = rsa_key;
+ ssl->rsa_decrypt = rsa_decrypt;
+ ssl->rsa_sign = rsa_sign;
+ ssl->rsa_key_len = rsa_key_len;
+}
+
+
+#if defined(POLARSSL_DHM_C)
+int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G )
+{
+ int ret;
+
+ if( ( ret = mpi_read_string( &ssl->dhm_P, 16, dhm_P ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "mpi_read_string", ret );
+ return( ret );
+ }
+
+ if( ( ret = mpi_read_string( &ssl->dhm_G, 16, dhm_G ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "mpi_read_string", ret );
+ return( ret );
+ }
+
+ return( 0 );
+}
+
+int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx )
+{
+ int ret;
+
+ if( ( ret = mpi_copy(&ssl->dhm_P, &dhm_ctx->P) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "mpi_copy", ret );
+ return( ret );
+ }
+
+ if( ( ret = mpi_copy(&ssl->dhm_G, &dhm_ctx->G) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "mpi_copy", ret );
+ return( ret );
+ }
+
+ return( 0 );
+}
+#endif /* POLARSSL_DHM_C */
+
+int ssl_set_hostname( ssl_context *ssl, const char *hostname )
+{
+ if( hostname == NULL )
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+ ssl->hostname_len = strlen( hostname );
+ ssl->hostname = (unsigned char *) malloc( ssl->hostname_len + 1 );
+
+ if( ssl->hostname == NULL )
+ return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+ memcpy( ssl->hostname, (const unsigned char *) hostname,
+ ssl->hostname_len );
+
+ ssl->hostname[ssl->hostname_len] = '\0';
+
+ return( 0 );
+}
+
+void ssl_set_sni( ssl_context *ssl,
+ int (*f_sni)(void *, ssl_context *,
+ const unsigned char *, size_t),
+ void *p_sni )
+{
+ ssl->f_sni = f_sni;
+ ssl->p_sni = p_sni;
+}
+
+void ssl_set_max_version( ssl_context *ssl, int major, int minor )
+{
+ ssl->max_major_ver = major;
+ ssl->max_minor_ver = minor;
+}
+
+void ssl_set_min_version( ssl_context *ssl, int major, int minor )
+{
+ ssl->min_major_ver = major;
+ ssl->min_minor_ver = minor;
+}
+
+void ssl_set_renegotiation( ssl_context *ssl, int renegotiation )
+{
+ ssl->disable_renegotiation = renegotiation;
+}
+
+void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy )
+{
+ ssl->allow_legacy_renegotiation = allow_legacy;
+}
+
+/*
+ * SSL get accessors
+ */
+size_t ssl_get_bytes_avail( const ssl_context *ssl )
+{
+ return( ssl->in_offt == NULL ? 0 : ssl->in_msglen );
+}
+
+int ssl_get_verify_result( const ssl_context *ssl )
+{
+ return( ssl->verify_result );
+}
+
+const char *ssl_get_ciphersuite_name( const int ciphersuite_id )
+{
+ switch( ciphersuite_id )
+ {
+#if defined(POLARSSL_ARC4_C)
+ case TLS_RSA_WITH_RC4_128_MD5:
+ return( "TLS-RSA-WITH-RC4-128-MD5" );
+
+ case TLS_RSA_WITH_RC4_128_SHA:
+ return( "TLS-RSA-WITH-RC4-128-SHA" );
+#endif
+
+#if defined(POLARSSL_DES_C)
+ case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+ return( "TLS-RSA-WITH-3DES-EDE-CBC-SHA" );
+
+ case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ return( "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA" );
+#endif
+
+#if defined(POLARSSL_AES_C)
+ case TLS_RSA_WITH_AES_128_CBC_SHA:
+ return( "TLS-RSA-WITH-AES-128-CBC-SHA" );
+
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ return( "TLS-DHE-RSA-WITH-AES-128-CBC-SHA" );
+
+ case TLS_RSA_WITH_AES_256_CBC_SHA:
+ return( "TLS-RSA-WITH-AES-256-CBC-SHA" );
+
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ return( "TLS-DHE-RSA-WITH-AES-256-CBC-SHA" );
+
+#if defined(POLARSSL_SHA2_C)
+ case TLS_RSA_WITH_AES_128_CBC_SHA256:
+ return( "TLS-RSA-WITH-AES-128-CBC-SHA256" );
+
+ case TLS_RSA_WITH_AES_256_CBC_SHA256:
+ return( "TLS-RSA-WITH-AES-256-CBC-SHA256" );
+
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+ return( "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256" );
+
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+ return( "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256" );
+#endif
+
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
+ case TLS_RSA_WITH_AES_128_GCM_SHA256:
+ return( "TLS-RSA-WITH-AES-128-GCM-SHA256" );
+
+ case TLS_RSA_WITH_AES_256_GCM_SHA384:
+ return( "TLS-RSA-WITH-AES-256-GCM-SHA384" );
+#endif
+
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C)
+ case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+ return( "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256" );
+
+ case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+ return( "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384" );
+#endif
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+ case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ return( "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA" );
+
+ case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ return( "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA" );
+
+ case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ return( "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA" );
+
+ case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ return( "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA" );
+
+#if defined(POLARSSL_SHA2_C)
+ case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ return( "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256" );
+
+ case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ return( "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256" );
+
+ case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ return( "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256" );
+
+ case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ return( "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256" );
+#endif
+#endif
+
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ case TLS_RSA_WITH_NULL_MD5:
+ return( "TLS-RSA-WITH-NULL-MD5" );
+ case TLS_RSA_WITH_NULL_SHA:
+ return( "TLS-RSA-WITH-NULL-SHA" );
+ case TLS_RSA_WITH_NULL_SHA256:
+ return( "TLS-RSA-WITH-NULL-SHA256" );
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+#if defined(POLARSSL_DES_C)
+ case TLS_RSA_WITH_DES_CBC_SHA:
+ return( "TLS-RSA-WITH-DES-CBC-SHA" );
+ case TLS_DHE_RSA_WITH_DES_CBC_SHA:
+ return( "TLS-DHE-RSA-WITH-DES-CBC-SHA" );
+#endif
+#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
+
+ default:
+ break;
+ }
+
+ return( "unknown" );
+}
+
+int ssl_get_ciphersuite_id( const char *ciphersuite_name )
+{
+#if defined(POLARSSL_ARC4_C)
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-RC4-128-MD5"))
+ return( TLS_RSA_WITH_RC4_128_MD5 );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-RC4-128-SHA"))
+ return( TLS_RSA_WITH_RC4_128_SHA );
+#endif
+
+#if defined(POLARSSL_DES_C)
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-3DES-EDE-CBC-SHA"))
+ return( TLS_RSA_WITH_3DES_EDE_CBC_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA"))
+ return( TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA );
+#endif
+
+#if defined(POLARSSL_AES_C)
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-AES-128-CBC-SHA"))
+ return( TLS_RSA_WITH_AES_128_CBC_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA"))
+ return( TLS_DHE_RSA_WITH_AES_128_CBC_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-AES-256-CBC-SHA"))
+ return( TLS_RSA_WITH_AES_256_CBC_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA"))
+ return( TLS_DHE_RSA_WITH_AES_256_CBC_SHA );
+
+#if defined(POLARSSL_SHA2_C)
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-AES-128-CBC-SHA256"))
+ return( TLS_RSA_WITH_AES_128_CBC_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-AES-256-CBC-SHA256"))
+ return( TLS_RSA_WITH_AES_256_CBC_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256"))
+ return( TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256"))
+ return( TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 );
+#endif
+
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-AES-128-GCM-SHA256"))
+ return( TLS_RSA_WITH_AES_128_GCM_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-AES-256-GCM-SHA384"))
+ return( TLS_RSA_WITH_AES_256_GCM_SHA384 );
+#endif
+
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
+ if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256"))
+ return( TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384"))
+ return( TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 );
+#endif
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA"))
+ return( TLS_RSA_WITH_CAMELLIA_128_CBC_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA"))
+ return( TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA"))
+ return( TLS_RSA_WITH_CAMELLIA_256_CBC_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA"))
+ return( TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA );
+
+#if defined(POLARSSL_SHA2_C)
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256"))
+ return( TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256"))
+ return( TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256"))
+ return( TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256"))
+ return( TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 );
+#endif
+#endif
+
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-NULL-MD5"))
+ return( TLS_RSA_WITH_NULL_MD5 );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-NULL-SHA"))
+ return( TLS_RSA_WITH_NULL_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-NULL-SHA256"))
+ return( TLS_RSA_WITH_NULL_SHA256 );
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+#if defined(POLARSSL_DES_C)
+ if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-DES-CBC-SHA"))
+ return( TLS_RSA_WITH_DES_CBC_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-DES-CBC-SHA"))
+ return( TLS_DHE_RSA_WITH_DES_CBC_SHA );
+#endif
+#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
+
+ return( 0 );
+}
+
+const char *ssl_get_ciphersuite( const ssl_context *ssl )
+{
+ if( ssl == NULL || ssl->session == NULL )
+ return NULL;
+
+ return ssl_get_ciphersuite_name( ssl->session->ciphersuite );
+}
+
+const char *ssl_get_version( const ssl_context *ssl )
+{
+ switch( ssl->minor_ver )
+ {
+ case SSL_MINOR_VERSION_0:
+ return( "SSLv3.0" );
+
+ case SSL_MINOR_VERSION_1:
+ return( "TLSv1.0" );
+
+ case SSL_MINOR_VERSION_2:
+ return( "TLSv1.1" );
+
+ case SSL_MINOR_VERSION_3:
+ return( "TLSv1.2" );
+
+ default:
+ break;
+ }
+ return( "unknown" );
+}
+
+const x509_cert *ssl_get_peer_cert( const ssl_context *ssl )
+{
+ if( ssl == NULL || ssl->session == NULL )
+ return NULL;
+
+ return ssl->session->peer_cert;
+}
+
+const int ssl_default_ciphersuites[] =
+{
+#if defined(POLARSSL_DHM_C)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA2_C)
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C)
+ TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
+#endif
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+#if defined(POLARSSL_SHA2_C)
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+#endif
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
+ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+#endif
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+#endif
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_SHA2_C)
+ TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+ TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
+#if defined(POLARSSL_SHA2_C)
+ TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+ TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
+#endif
+#if defined(POLARSSL_DES_C)
+ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+#endif
+#endif
+
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA2_C)
+ TLS_RSA_WITH_AES_256_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C)
+ TLS_RSA_WITH_AES_256_GCM_SHA384,
+#endif /* POLARSSL_SHA2_C */
+ TLS_RSA_WITH_AES_256_CBC_SHA,
+#endif
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_SHA2_C)
+ TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+ TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
+#endif
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA2_C)
+ TLS_RSA_WITH_AES_128_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
+ TLS_RSA_WITH_AES_128_GCM_SHA256,
+#endif /* POLARSSL_SHA2_C */
+ TLS_RSA_WITH_AES_128_CBC_SHA,
+#endif
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_SHA2_C)
+ TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+ TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
+#endif
+#if defined(POLARSSL_DES_C)
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+#endif
+#if defined(POLARSSL_ARC4_C)
+ TLS_RSA_WITH_RC4_128_SHA,
+ TLS_RSA_WITH_RC4_128_MD5,
+#endif
+ 0
+};
+
+/*
+ * Perform a single step of the SSL handshake
+ */
+int ssl_handshake_step( ssl_context *ssl )
+{
+ int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+
+#if defined(POLARSSL_SSL_CLI_C)
+ if( ssl->endpoint == SSL_IS_CLIENT )
+ ret = ssl_handshake_client_step( ssl );
+#endif
+
+#if defined(POLARSSL_SSL_SRV_C)
+ if( ssl->endpoint == SSL_IS_SERVER )
+ ret = ssl_handshake_server_step( ssl );
+#endif
+
+ return( ret );
+}
+
+/*
+ * Perform the SSL handshake
+ */
+int ssl_handshake( ssl_context *ssl )
+{
+ int ret = 0;
+
+ SSL_DEBUG_MSG( 2, ( "=> handshake" ) );
+
+ while( ssl->state != SSL_HANDSHAKE_OVER )
+ {
+ ret = ssl_handshake_step( ssl );
+
+ if( ret != 0 )
+ break;
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= handshake" ) );
+
+ return( ret );
+}
+
+/*
+ * Renegotiate current connection
+ */
+int ssl_renegotiate( ssl_context *ssl )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) );
+
+ if( ssl->state != SSL_HANDSHAKE_OVER )
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+ ssl->state = SSL_HELLO_REQUEST;
+ ssl->renegotiation = SSL_RENEGOTIATION;
+
+ if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
+ return( ret );
+
+ if( ( ret = ssl_handshake( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_handshake", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) );
+
+ return( 0 );
+}
+
+/*
+ * Receive application data decrypted from the SSL layer
+ */
+int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len )
+{
+ int ret;
+ size_t n;
+
+ SSL_DEBUG_MSG( 2, ( "=> read" ) );
+
+ if( ssl->state != SSL_HANDSHAKE_OVER )
+ {
+ if( ( ret = ssl_handshake( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_handshake", ret );
+ return( ret );
+ }
+ }
+
+ if( ssl->in_offt == NULL )
+ {
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ if( ret == POLARSSL_ERR_SSL_CONN_EOF )
+ return( 0 );
+
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msglen == 0 &&
+ ssl->in_msgtype == SSL_MSG_APPLICATION_DATA )
+ {
+ /*
+ * OpenSSL sends empty messages to randomize the IV
+ */
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ if( ret == POLARSSL_ERR_SSL_CONN_EOF )
+ return( 0 );
+
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+ }
+
+ if( ssl->in_msgtype == SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "received handshake message" ) );
+
+ if( ssl->endpoint == SSL_IS_CLIENT &&
+ ( ssl->in_msg[0] != SSL_HS_HELLO_REQUEST ||
+ ssl->in_hslen != 4 ) )
+ {
+ SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ if( ssl->disable_renegotiation == SSL_RENEGOTIATION_DISABLED ||
+ ( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
+ ssl->allow_legacy_renegotiation == SSL_LEGACY_NO_RENEGOTIATION ) )
+ {
+ SSL_DEBUG_MSG( 3, ( "ignoring renegotiation, sending alert" ) );
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ /*
+ * SSLv3 does not have a "no_renegotiation" alert
+ */
+ if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+ }
+ else
+ {
+ if( ( ret = ssl_send_alert_message( ssl,
+ SSL_ALERT_LEVEL_WARNING,
+ SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 )
+ {
+ return( ret );
+ }
+ }
+ }
+ else
+ {
+ if( ( ret = ssl_renegotiate( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_renegotiate", ret );
+ return( ret );
+ }
+
+ return( POLARSSL_ERR_NET_WANT_READ );
+ }
+ }
+ else if( ssl->in_msgtype != SSL_MSG_APPLICATION_DATA )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad application data message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ ssl->in_offt = ssl->in_msg;
+ }
+
+ n = ( len < ssl->in_msglen )
+ ? len : ssl->in_msglen;
+
+ memcpy( buf, ssl->in_offt, n );
+ ssl->in_msglen -= n;
+
+ if( ssl->in_msglen == 0 )
+ /* all bytes consumed */
+ ssl->in_offt = NULL;
+ else
+ /* more data available */
+ ssl->in_offt += n;
+
+ SSL_DEBUG_MSG( 2, ( "<= read" ) );
+
+ return( (int) n );
+}
+
+/*
+ * Send application data to be encrypted by the SSL layer
+ */
+int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len )
+{
+ int ret;
+ size_t n;
+
+ SSL_DEBUG_MSG( 2, ( "=> write" ) );
+
+ if( ssl->state != SSL_HANDSHAKE_OVER )
+ {
+ if( ( ret = ssl_handshake( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_handshake", ret );
+ return( ret );
+ }
+ }
+
+ n = ( len < SSL_MAX_CONTENT_LEN )
+ ? len : SSL_MAX_CONTENT_LEN;
+
+ if( ssl->out_left != 0 )
+ {
+ if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
+ return( ret );
+ }
+ }
+ else
+ {
+ ssl->out_msglen = n;
+ ssl->out_msgtype = SSL_MSG_APPLICATION_DATA;
+ memcpy( ssl->out_msg, buf, n );
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write" ) );
+
+ return( (int) n );
+}
+
+/*
+ * Notify the peer that the connection is being closed
+ */
+int ssl_close_notify( ssl_context *ssl )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> write close notify" ) );
+
+ if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
+ return( ret );
+ }
+
+ if( ssl->state == SSL_HANDSHAKE_OVER )
+ {
+ if( ( ret = ssl_send_alert_message( ssl,
+ SSL_ALERT_LEVEL_WARNING,
+ SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 )
+ {
+ return( ret );
+ }
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write close notify" ) );
+
+ return( ret );
+}
+
+void ssl_transform_free( ssl_transform *transform )
+{
+#if defined(POLARSSL_ZLIB_SUPPORT)
+ deflateEnd( &transform->ctx_deflate );
+ inflateEnd( &transform->ctx_inflate );
+#endif
+
+ memset( transform, 0, sizeof( ssl_transform ) );
+}
+
+void ssl_handshake_free( ssl_handshake_params *handshake )
+{
+#if defined(POLARSSL_DHM_C)
+ dhm_free( &handshake->dhm_ctx );
+#endif
+ memset( handshake, 0, sizeof( ssl_handshake_params ) );
+}
+
+void ssl_session_free( ssl_session *session )
+{
+ if( session->peer_cert != NULL )
+ {
+ x509_free( session->peer_cert );
+ free( session->peer_cert );
+ }
+
+ memset( session, 0, sizeof( ssl_session ) );
+}
+
+/*
+ * Free an SSL context
+ */
+void ssl_free( ssl_context *ssl )
+{
+ SSL_DEBUG_MSG( 2, ( "=> free" ) );
+
+ free( ssl->ciphersuites );
+
+ if( ssl->out_ctr != NULL )
+ {
+ memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
+ free( ssl->out_ctr );
+ }
+
+ if( ssl->in_ctr != NULL )
+ {
+ memset( ssl->in_ctr, 0, SSL_BUFFER_LEN );
+ free( ssl->in_ctr );
+ }
+
+#if defined(POLARSSL_DHM_C)
+ mpi_free( &ssl->dhm_P );
+ mpi_free( &ssl->dhm_G );
+#endif
+
+ if( ssl->transform )
+ {
+ ssl_transform_free( ssl->transform );
+ free( ssl->transform );
+ }
+
+ if( ssl->handshake )
+ {
+ ssl_handshake_free( ssl->handshake );
+ ssl_transform_free( ssl->transform_negotiate );
+ ssl_session_free( ssl->session_negotiate );
+
+ free( ssl->handshake );
+ free( ssl->transform_negotiate );
+ free( ssl->session_negotiate );
+ }
+
+ if( ssl->session )
+ {
+ ssl_session_free( ssl->session );
+ free( ssl->session );
+ }
+
+ if ( ssl->hostname != NULL)
+ {
+ memset( ssl->hostname, 0, ssl->hostname_len );
+ free( ssl->hostname );
+ ssl->hostname_len = 0;
+ }
+
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+ if( ssl_hw_record_finish != NULL )
+ {
+ SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_finish()" ) );
+ ssl_hw_record_finish( ssl );
+ }
+#endif
+
+ SSL_DEBUG_MSG( 2, ( "<= free" ) );
+
+ /* Actually clear after last debug message */
+ memset( ssl, 0, sizeof( ssl_context ) );
+}
+
+#endif
diff --git a/polarssl/timing.c b/polarssl/timing.c
new file mode 100644
index 0000000..0273d1a
--- /dev/null
+++ b/polarssl/timing.c
@@ -0,0 +1,312 @@
+/*
+ * Portable interface to the CPU cycle counter
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_TIMING_C)
+
+#include "polarssl/timing.h"
+
+#if defined(_WIN32)
+
+#include