toring passwords and secret configuration is a challenge for an application. Ada Keystore is a library that stores arbitrary content by encrypting them in secure keystore (AES-256, HMAC-256).
The talk presents the project and shows how to use the Ada Keystore library to get or store secret information in a secure manner. The presentation explains how the Ada features such as types, protected types, tasks, pre/post conditions have helped during the development of this project.
2. https://github.com/stcarrez/ada-keystore 2
Why Ada Keystore?
●
Store sensitive parameters of an Ada server :
– Database connection passwords
– API secret keys
●
Tool to store sensitive information :
– Passwords and accounts
– Encrypted documents without exposing their
keys
3. https://github.com/stcarrez/ada-keystore 3
Getting a secret (1)
with Keystore.Files;
function Get_Secret return String is
WS : Keystore.Files.Wallet_File;
Pass : Keystore.Secret_Key:= Keystore.Create ("...");
begin
WS.Open (Pass, “secure.akt”);
return WS.Get ("api-key");
end Get_Secret;
●
Open keystore with simple password
(simple but less secure : password in code!)
4. https://github.com/stcarrez/ada-keystore 4
Getting a secret (2)
with Keystore.GPG;
with Keystore.Passwords.GPG;
with Keystore.Files;
function Get_Secret return String is
WS : Keystore.Files.Wallet_File;
Ctx : Keystore.Passwords.GPG.Context_Type;
begin
Keystore.GPG.Open (WS, Ctx, “secure.akt”);
return WS.Get ("api-key");
end Get_Secret;
●
Open keystore protected with GPG
6. https://github.com/stcarrez/ada-keystore 6
Ada Keystore: with multiple keys
Directory key
Master key block
Data info key
Data key key
Data keys
Data keys
Signature key
User password
GPG protected
key
Data fragment
Data fragment
Data fragment
Data fragment
Data fragment
Directory keys Encrypted Data
7. https://github.com/stcarrez/ada-keystore 7
Ada Keystore: with blocks
(unchained)
HMAC-256HDR
(1815-12-10)
(1852-11-27)
Ada
HMAC-256UUID
Storage
ID
HDR Data Storage Info + HMAC
Directory Name Entry Data block indexes & keys
HMAC-256HDR Data fragment info HMAC-256 Data Fragment
Header block
Directory block
Data block
Master key block
...
HMAC-256HDR Wallet info Key slot 1UUID Key slot 7...
4K
8. https://github.com/stcarrez/ada-keystore 8
Ada Keystore: key protection
Wallet master key slot N (512 bytes)
key slot Nsalt key N
HMAC
256
= ?
AES-256
CBC
Wallet Master Keys
(32 bytes) (240 bytes)
key key
(256 bits)
key IV
(128 bits)
dat key
(256 bits)
dat IV
(128 bits)
dir key
(256 bits)
dir IV
(128 bits)
Wallet master key block
AES-256
CBC
PBKDF2
HMAC
256
ctr slot N
(4 bytes)
Sign N HMAC
(32 bytes) (32 bytes)
PBKDF2
HMAC
256
(4 bytes)
salt IV N
(32 bytes)
HMAC-256HDR Wallet info Key slot 1UUID Key slot 7...
Wallet Header Key, wallet header IV, Block ID
User password NO, invalid
password
YES, valid password
dir sign
(256 bits)
dat sign
(256 bits)
key sign
(256 bits)
Key
IV
HMAC
256
= ?
NO, invalid
block
YES, valid block
Wallet Sign
9. https://github.com/stcarrez/ada-keystore 9
Ada Keystore: GPG protection
Wallet master key slot N (512 bytes)
key slot N
HMAC
256
= ?
AES-256
CBC
Wallet Master Keys
(240 bytes)
key key
(256 bits)
key IV
(128 bits)
dat key
(256 bits)
dat IV
(128 bits)
dir key
(256 bits)
dir IV
(128 bits)
Wallet master key block
AES-256
CBC
Sign N HMAC
(32 bytes) (32 bytes)
HMAC-256HDR Wallet info Key slot 1UUID Key slot 7...
NO, invalid
password
YES, valid password
dir sign
(256 bits)
dat sign
(256 bits)
key sign
(256 bits)
Key, IV
GPG2
GPG Private key
Header block
Key
(32 bytes)
IV
(16 bytes)
IV Key
(16 bytes) (32 bytes)
(1815-12-10)
(1852-11-27)
Ada
HMAC-256UUID
Storage
ID
HDR Data Storage Info + HMAC
Sign
(32 bytes)
HMAC
256
= ? NO, invalid
block
YES, valid block
header tag
(4 bytes)
10. https://github.com/stcarrez/ada-keystore 10
Ada Keystore: directory encryption
Directory block
AES-256
CBC
HMAC-256HDR ...
Directory Key, directory IV, Block ID
HMAC
256
Directory Sign
Directory Name Entry Data block indexes & keys...
Per data fragment encryption keys
Name
(N bytes)
Entry ID
(4 bytes)
key
(256 bits)
IV
(128 bits)
Block NumStore ID
(4 bytes)(4 bytes)(4 bytes)
Entry ID
HMAC-256HDR Data fragment info HMAC-256 Data Fragment HMAC-256HDR Data fragment info HMAC-256 Data Fragment
11. https://github.com/stcarrez/ada-keystore 11
Ada Keystore: data encryption
Data block
AES-256
CBC
...
Data Key, IV, Block ID
HMAC
256
Data Sign
HMAC-256
HDR
Data fragment info HMAC-256 Data Fragment
AES-256
CBC
HMAC
256
Data entry descriptor
HMAC
(256 bits)
Data OffsetSlot Size
(8 bytes)(2 bytes)(4 bytes)
Entry ID
Data fragment Key, IV, Block ID
Data Fragment
12. https://github.com/stcarrez/ada-keystore 12
Ada Keystore: directory decryption
Directory block
AES-256
CBC
HMAC-256HDR ...
Directory Key, directory IV, Block ID HMAC
256
= ?
NO, invalid
block
YES, valid block
Directory Sign
Directory Name Entry Data block indexes & keys...
Per data fragment encryption keys
Name
(N bytes)
Entry ID
(4 bytes)
key
(256 bits)
IV
(128 bits)
Block NumStore ID
(4 bytes)(4 bytes)(4 bytes)
Entry ID
HMAC-256HDR Data fragment info HMAC-256 Data Fragment HMAC-256HDR Data fragment info HMAC-256 Data Fragment
13. https://github.com/stcarrez/ada-keystore 13
Ada Keystore: data decryption
Data block
AES-256
CBC
...
Data Key, IV, Block ID HMAC
256
= ?
NO, invalid
block
YES, valid block
Data Sign
HMAC-256
HDR
Data fragment info HMAC-256 Data Fragment
AES-256
CBC
HMAC
256
Data entry descriptor
HMAC
(256 bits)
Data OffsetSlot Size
(8 bytes)(2 bytes)(4 bytes)
Entry ID
= ?
NO, invalid
fragment
YES, valid fragment
Data fragment Key, IV, Block ID
Data Fragment
14. https://github.com/stcarrez/ada-keystore 14
Ada Keystore: more complexity
Data block
AES-256
CBC
...
Data Key, IV, Block ID HMAC
256
= ?
NO, invalid
block
YES, valid block
Data Sign
Name
(N bytes)
Entry ID
(4 bytes) (4 bytes)
Entry ID
HMAC-256
HDR
Data fragment info HMAC-256 Data Fragment
AES-256
CBC
HMAC
256
Data entry descriptor
HMAC
(256 bits)
Data OffsetSlot Size
(8 bytes)(2 bytes)(4 bytes)
Entry ID
= ?
NO, invalid
fragment
YES, valid fragment
Data fragment Key, IV, Block ID
Data Fragment
Directory block
AES-256
CBC
HMAC-256HDR ...
Directory Key, directory IV, Block ID HMAC
256
= ?
NO, invalid
block
YES, valid block
Directory Sign
Directory Name Entry Data block indexes & keys...
Per data fragment encryption keys
Name
(N bytes)
Entry ID
(4 bytes)
key
(256 bits)
IV
(128 bits)
Block NumStore ID
(4 bytes)(4 bytes)(4 bytes)
Entry ID
HMAC-256HDR Data fragment info HMAC-256 Data Fragment HMAC-256HDR Data fragment info HMAC-256 Data Fragment
Wallet master key slot N (512 bytes)
key slot Nsalt key N
HMAC
256
= ?
AES-256
CBC
Wallet Master Keys
(32 bytes) (240 bytes)
key key
(256 bits)
key IV
(128 bits)
dat key
(256 bits)
dat IV
(128 bits)
dir key
(256 bits)
dir IV
(128 bits)
Wallet master key block
AES-256
CBC
PBKDF2
HMAC
256
ctr slot N
(4 bytes)
Sign N HMAC
(32 bytes) (32 bytes)
PBKDF2
HMAC
256
(4 bytes)
salt IV N
(32 bytes)
HMAC-256HDR Wallet info Key slot 1UUID Key slot 7...
Wallet Header Key, wallet header IV, Block ID
User password NO, invalid
password
YES, valid password
dir sign
(256 bits)
dat sign
(256 bits)
key sign
(256 bits)
Key
IV
HMAC
256
= ?
NO, invalid
block
YES, valid block
Wallet Sign
Update data
Secure data erase
Insert data
Protect keys
Thread safe API
Multi-task encryption/decryption
Prevent security holes
15. https://github.com/stcarrez/ada-keystore 15
Ada benefit : limited types
●
Use limited record :
– Encryption keys cannot be copied
– Secret key content visible only to AES operations
●
Use Ada.Finalization.Limited_Controlled :
– Erase encryption keys when object is released
type Secret_Key (Length : Key_Length) is limited private;
16. https://github.com/stcarrez/ada-keystore 16
Ada benefit : subtypes
●
Use subtype to constraint index computation :
– Detect index errors when they are computed not
when we access the data
subtype Buffer_Size is Stream_Element_Offset range 0 .. 4064;
subtype Block_Index is Stream_Element_Offset range 1 .. 4064;
subtype Block_Type is Stream_Element_Array (Block_Index);
Key_Pos := Key_Header_Pos - Key_Slot_Size (Iterator.Key_Count);
Buf.Data (Key_Pos .. Key_Pos + Key_Size - 1) := ...;
better to raise Constraint_Error here
bounds still verified
17. https://github.com/stcarrez/ada-keystore 17
Ada benefit : private child package
●
Use private child package :
– Restrict scope of operations
– Helps in refactoring decisions
EntriesData Keys
Files Headers Refs Workers
Containers
Files Tools GPG
Cmds
Files GPG
Passwords
Keystore
Repository
Buffers
Marshallers
IO Keys
Random
Input Keys
Unsafe
18. https://github.com/stcarrez/ada-keystore 18
Ada benefit : precondition
●
Use Preconditions :
– Nice for API constraints
– Helpful to detect internal errors earlier
function Contains
(Container : in Wallet;
Name : in String) return Boolean is abstract with
Pre'Class => Container.Is_Open;
procedure Put_Unsigned_32
(Into : in out Marshaller;
Value : in Interfaces.Unsigned_32) with
Pre => Into.Pos <= Block_Type'Last - 4;
19. https://github.com/stcarrez/ada-keystore 19
Ada benefit : postcondition
●
Use Postconditions :
– Nice for API clarification
– More complex to write
function Get_Header
(From : in out Marshaller) return Unsigned_32 with
Post => From.Pos = Block_Type'First + 3;
procedure Get_Keys
(From : in Key_Provider;
Key : out Secret_Key;
IV : out Secret_Key;
Sign : out Secret_Key) is abstract with
Post'Class => Key.Length = 32 and IV.Length = 16
and Sign.Length = 32;
20. https://github.com/stcarrez/ada-keystore 20
Ada benefit : protected types
●
Use protected types :
– Concurrent access to keystore objects
– Holds de keystore internal data structures
protected type Wallet_Container is
procedure Open (...);
procedure Create (...);
procedure Add (...);
...
end Wallet_Container;
22. https://github.com/stcarrez/ada-keystore 22
Ada Keystore Work Queues
AES-256
CBC
HMAC
256
READ
BLOCKExecutor
Queue
Executor Task #1
Sequence
Queue
AES-256
CBC
HMAC
256
Executor Task #N
HMAC-256HDR Data fragment info HMAC-256 Data Fragment
HMAC-256HDR Data fragment info HMAC-256 Data Fragment
HMAC-256HDR Data fragment info HMAC-256 Data Fragment
Data Fragment #1 Data Fragment #2 Data Fragment #N
Prepare
Work
Collect
Work
READ
BLOCK
Work Pool
23. https://github.com/stcarrez/ada-keystore 23
Conclusion
●
Writing a secure keystore is hard :
– insert, update, remove data entries that look random
– don’t leak secret keys
●
Project succeeded thanks to Ada :
– many errors prevented by the language
– no buffer overflow, runtime error detection
●
Secure storage made simple for Ada :
– simple Ada API (Open, Create, Add, Get, Remove)
– https://ada-keystore.readthedocs.io/en/latest/