···44#mol-chapter("Key Pairs")
5566// what are keypair objects ?
77-Key pairs in Twizzler are the representation of the cryptographic signing schemes
88-used to create a signed capability, discussed in 3.1.
99-We design the keypair objects to be agnostic towards what cryptographic
1010-schemes are underneath, allowing for the underlying algorithm to be changed
1111-@twizzler. The keys themselves are stored inside of objects, allowing for
1212-persistent or volatile storage depending on object specification, and
1313-allows for keys themselves to be treated as any other object and have security
1414-policy applied to them. This allows for powerful primitives and rich
1515-expressiveness for describing secruity policy, while also being flexible enough
1616-to make basic policy easy.
77+Key pairs in Twizzler are the representation of the cryptographic signing
88+schemes used to create a signed capability, discussed in 3.1. We design
99+the keypair objects to be agnostic towards what cryptographic schemes are
1010+underneath, allowing for the underlying algorithm to be changed @twizzler. The
1111+keys themselves are stored inside of objects, allowing for persistent or
1212+volatile storage depending on object specification, and allows for keys
1313+themselves to be treated as any other object and have security policy applied
1414+to them. This allows for powerful primitives and rich expressiveness for
1515+describing secruity policy, while also being flexible enough to make basic
1616+policy easy.
17171818-Suppose for instance we have Alice on Twizzler, and all users on twizzler
1919-have a "user-root" keypair that allows for them to create an arbitrary number of
2020-objects. Also suppose that access to this user-root keypair is protected by some
2121-login program, where only alice can log in. This now means that Alice now
2222-can create new keypairs, protected by her user-root keypair. Since all her
2323-new keypairs originate from her original user-root keypair, only she can access
2424-the keys required to create new signatures of hers. It forms an elegant solution for
2525-capability creation without the involvement of the kernel.
2626-2727-2828-2929-3030-// how are they represented in twizzler ?
31183219== Abstraction
33203421The `SigningKey` struct is a fixed length byte array with a length field
3522and an enum specifying what algorithm that key should be interpreted as.
3636-Currently we use the Elliptic Curve Digital Signature Algorithm (ECDSA)
3737-@ecdsa to sign capabilities and verify them, but the simplistic dat
3838-arepresentation allows for any arbitrary alogrithm to be used as long as
3939-the key can be represented as bytes.
2323+Currently we use the Elliptic Curve Digital Signature Algorithm (ECDSA) @ecdsa
2424+to sign capabilities and verify them, but the simplistic data representation
2525+allows for any arbitrary alogrithm to be used as long as the key can be
2626+represented as bytes.
40274141-Additionally this specification allows
4242-for backward compatibility, allowing for an outdated signing scheme to be used in
4343-support of older programs / files. An existing drawback for backward compatibility is the
4444-maximum size of the buffer we store the key in. Currently we set the maximum size as 256 bytes,
4545-meaning if a future cryptographic signing scheme was to be found with a private key size
4646-larger than 256 bytes, we would have to drop backwards compatibility. Sure this
4747-can be prevented by setting the maximum size to something larger, but that a tradeoff
4848-between possible cryptographic schemes vs the real on-disk cost of larger buffers.
2828+Additionally this specification allows for backward compatibility, allowing
2929+for an outdated signing scheme to be used in support of older programs /
3030+files. An existing drawback for backward compatibility is the maximum size
3131+of the buffer we store the key in. Currently we set the maximum size as 256
3232+bytes, meaning if a future cryptographic signing scheme was to be found with
3333+a private key size larger than 256 bytes, we would have to drop backwards
3434+compatibility. Sure this can be prevented by setting the maximum size to
3535+something larger, but that a tradeoff between possible cryptographic schemes
3636+vs the real on-disk cost of larger buffers.
49375038== Compartmentalization
5139// how they can be used to sign multiple objects (compartmentalization)
52405341To create an object in twizzler, you specify the id of a verifying key
5442object so the kernel knows which key to use to verify any
5555-capabilities permitting access to the object. You can also specify
5656-default protections for an object or create a capability with the signing
5757-key and any desired permissions.
5858-5959-The neat thing about this design is that you can use a single keypair in-order to use
6060-any arbitrary amount of objects. An example could be a colletion of objects holding files for a class, and grouping all of them
6161-under the same key. In short, having this flexibility allows for a significant debloating
6262-of the filesystem, comparted to creating a new keypair for every single object.
4343+capabilities permitting access to the object. Since keys are represented as objects
4444+in twizzler, security policy applies on them as well, creating satisfying
4545+solutions in regards to key management.
63466464-In planned future work , as we talk more about in
6565-we can investiage the This results in the possibility of finegrained
6666-access control to semantic groupings of objects.
6767-// what the fuck am i trying to say
4747+Suppose for instance we have Alice on Twizzler, and all users on twizzler have
4848+a "user-root" keypair that allows for them to create an arbitrary number of
4949+objects. Also suppose that access to this user-root keypair is protected by
5050+some login program, where only alice can log in. This now means that Alice
5151+now can create new keypair objects from her user-root keypair. Since all
5252+her new keypairs originate from her original user-root keypair, only she can
5353+access the keys required to create new signatures allowing permissions into
5454+her objects. It forms an elegant solution for capability creation without
5555+the involvement of the kernel.
68566969-// all it does is make creation easier, since you only need one pair, it doesnt
7070-// restrict capabilities or whatever. It's just a benefit since we dont have to worry
7171-// about managing a keypair for every single object
72577358#load-bib(read("refs.bib"))
+111-5
5-results.typ
···11#import "template.typ": *
22+33+#import "@preview/unify:0.7.1"
24#mol-chapter("Results")
3546// benchmarking
···1315//
1416// take measurements without security checks too so you can see the security overhead
1517//
1616-All testing was done in QEMU, with a Ryzen 5 2600 processor.
17181919+== Validation
18201919-== Validation
2121+The first test is a basic scenario as a check to make sure the system is behaving as intended, and
2222+a more expressive test to demonstrate the flexibility of the model. Eventually I intend to work with
2323+my advisor and peers to form a proof of correctness for the security model, as well
2424+as empirical testing to demonstrate its rigidity.
20252126=== Basic
2222-2323-2424-=== Expressive
2727+TBA
2828+== Expressive
2929+TBA
253026312732== Micro Benchmarks
3333+Additionally we have microbenchmarks of core security operations in Twizzler. All
3434+benchmarks were ran with a Ryzen 5 2600, with Twizzler virtualized in QEMU. Unfortunately
3535+I ran out of time to perform benchmarks on bare metal, but they should be the same, if
3636+not more, performant.
28372938=== Kernel
30394040+Theres a couple things we benchmark inside the kernel, including core cryptographic
4141+operations like signature generation and verification, as well as the total time it takes
4242+to verify a capability.
4343+#figure(
4444+table(
4545+ columns: (auto, auto),
4646+ inset: 10pt,
4747+ align: center,
4848+ table.header(
4949+ [Benchmark], [Time]
5050+ ),
5151+ [
5252+ Hashing (Sha256)
5353+ ],
5454+ [
5555+ 267.86 ns $plus.minus 163$ ns
5656+ ],
5757+ [
5858+ Hashing (Blake3)
5959+ ],
6060+ [
6161+ 125.99 ns $plus.minus 117$ ns
6262+ ],
6363+ [
6464+ Signature Generation (ECDSA)
6565+ ],
6666+ [
6767+ 199.90 $\u{00B5}s plus.minus 9.45 \u{00B5}s$
6868+ ],
6969+7070+ [
7171+ Signature Verification (ECDSA)
7272+ ],
7373+ [
7474+ 342.20 $\u{00B5}s plus.minus 6.28 \u{00B5}s$
7575+ ] ,
7676+ [
7777+ Capability Verification (ECDSA, Blake3)
7878+ ],
7979+ [
8080+ 343.59 $\u{00B5}s plus.minus 5.32 \u{00B5}s$
8181+ ]
8282+),
8383+caption: [Collection of Kernel Benchmarking Results]
8484+)
8585+8686+We see that signatures are vastly more expensive than hashing, on an order
8787+of $10^3$, meaning that your choice of hashing algorithm doesnt affection the
8888+total time taken for the verification of a capability. It's also important to
8989+note that this cost of verifying a capability for access is done on the first
9090+pagefault, then the kernel uses caching to store the granted permissions and
9191+provieds those on subsequent page faults into that object. In the future I hope
9292+to measure the difference between a cached and uncached verification. Secondly
9393+we only measure verification inside kernel space; as disscussed in section 3,
9494+capability creation only takes place in user space.
31953296=== UserSpace
9797+9898+In userspace we benchmark keypair and capability creation, as these operations are core to
9999+creating security policy.
100100+101101+102102+#figure(
103103+table(
104104+ columns: (auto, auto),
105105+ inset: 10pt,
106106+ align: center,
107107+ table.header(
108108+ [Benchmark], [Time]
109109+ ),
110110+ [
111111+ Capability Creation
112112+ ],
113113+ [
114114+ 347.97 $\u{00B5}s plus.minus 5.78 \u{00B5}s$
115115+ ],
116116+ [
117117+ Keypair Objects Creation
118118+ ],
119119+ [
120120+ 651.69$\u{00B5}s plus.minus 187.90 \u{00B5}s$
121121+ ],
122122+ [
123123+ Security Context Creation
124124+ ],
125125+ [
126126+ 282.10$\u{00B5}s plus.minus 119.90 \u{00B5}s$
127127+ ],
128128+),
129129+caption: [Collection of UserSpace Benchmarking Results]
130130+)
131131+132132+Almost all the time spent in creating a capability is the cryptographic operations used
133133+to form its signature, which is why its in the same ballpark as signature creation we saw earlier.
134134+135135+The high varince in Keypair objects and Security contexts creation happens from the
136136+unpredictable time it takes for the kernel to create an object on disk. The reason keypair's
137137+are almost 2x more expensive since it creates two seperate objects, one for the signing key,
138138+and one for the verifying key.
+20-1
6-conclusion.typ
···2233#mol-chapter("Conclusion")
4455+In short we provide a general overview of the critical security
66+components for security system in Twizzler, along with
77+implementation details and desgin descisions. The evaluation programs show how
88+security policy can be expressed and verifies that the kernel is enforcing as
99+programmed. Lastly we go over microbenchmarks to show and explain the cost of these operations.
1010+1111+512== Future Works
613714In the future I hope to take the primitives created during my thesis, and apply them towards
88-the implementation of Decentralized Information Flow Control, as described in
1515+the implementation of Decentralized Information Flow Control, as described in @flume, into
1616+the Twizzler security model. Additionally I would love to see how the current security model
1717+evolves once we start adding distributed computing support to Twizzler, as described in
1818+the orignal paper @twizzler.
1919+2020+2121+== Acknowledgements
2222+2323+I couldn't have done the work for this thesis and for Twizzler if it wasn't for the
2424+support I've recieved from my advisor Owen Arden and my technical mentor Daniel Bittman! I
2525+owe both of you so much, not just for the class credit but also for how much I've learned in
2626+this endeavor. Thanks guys!
2727+92810291130#load-bib(read("refs.bib"))
+2-2
template.typ
···9898 align(alignment.left, [
9999 #set par(first-line-indent: 0em)
100100101101- *Date of the public defence:*
101101+ // *Date of the public defence:*
102102103103- _#defence-date _
103103+ // _#defence-date _
104104105105 #colbreak()
106106