Adding documentation for Key-wrap tests.
NOKEYCHECK=True PiperOrigin-RevId: 222393282 GitOrigin-RevId: 3b3559b215aa7bd121611c501860db3a937b9e03
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<svg viewBox="0 0 450 340"
|
||||
xmlns="http://www.w3.org/2000/svg" version="1.1">
|
||||
<style>
|
||||
.label { font: italic 14px sans-serif; }
|
||||
</style><rect x="0" y="0" width="450" height="340" fill="white" stroke="none" stroke-width="0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="51.25,40 51.25,56.4"/>
|
||||
<polygon fill="black" points="51.25,60 53.05,56.4 49.45,56.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="73.75,40 73.75,56.4"/>
|
||||
<polygon fill="black" points="73.75,60 75.55,56.4 71.95,56.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="138.75,40 138.75,56.4"/>
|
||||
<polygon fill="black" points="138.75,60 140.55,56.4 136.95,56.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="203.75,40 203.75,56.4"/>
|
||||
<polygon fill="black" points="203.75,60 205.55,56.4 201.95,56.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="268.75,40 268.75,56.4"/>
|
||||
<polygon fill="black" points="268.75,60 270.55,56.4 266.95,56.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="333.75,40 333.75,56.4"/>
|
||||
<polygon fill="black" points="333.75,60 335.55,56.4 331.95,56.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="398.75,40 398.75,56.4"/>
|
||||
<polygon fill="black" points="398.75,60 400.55,56.4 396.95,56.4"/>
|
||||
<rect x="40" y="60" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="51.25,80 51.25,85.0 95.0,85.0 95.0,55.0 116.25,55.0 116.25,56.4"/>
|
||||
<polygon fill="black" points="116.25,60 118.05,56.4 114.45,56.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="73.75,80 73.75,96.4"/>
|
||||
<polygon fill="black" points="73.75,100 75.55,96.4 71.95,96.4"/>
|
||||
<rect x="105" y="60" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="116.25,80 116.25,85.0 160.0,85.0 160.0,55.0 181.25,55.0 181.25,56.4"/>
|
||||
<polygon fill="black" points="181.25,60 183.05,56.4 179.45,56.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="138.75,80 138.75,96.4"/>
|
||||
<polygon fill="black" points="138.75,100 140.55,96.4 136.95,96.4"/>
|
||||
<rect x="170" y="60" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="181.25,80 181.25,85.0 225.0,85.0 225.0,55.0 246.25,55.0 246.25,56.4"/>
|
||||
<polygon fill="black" points="246.25,60 248.05,56.4 244.45,56.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="203.75,80 203.75,96.4"/>
|
||||
<polygon fill="black" points="203.75,100 205.55,96.4 201.95,96.4"/>
|
||||
<rect x="235" y="60" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="246.25,80 246.25,85.0 290.0,85.0 290.0,55.0 311.25,55.0 311.25,56.4"/>
|
||||
<polygon fill="black" points="311.25,60 313.05,56.4 309.45,56.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="268.75,80 268.75,96.4"/>
|
||||
<polygon fill="black" points="268.75,100 270.55,96.4 266.95,96.4"/>
|
||||
<rect x="300" y="60" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="311.25,80 311.25,85.0 355.0,85.0 355.0,55.0 376.25,55.0 376.25,56.4"/>
|
||||
<polygon fill="black" points="376.25,60 378.05,56.4 374.45,56.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="333.75,80 333.75,96.4"/>
|
||||
<polygon fill="black" points="333.75,100 335.55,96.4 331.95,96.4"/>
|
||||
<rect x="365" y="60" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="398.75,80 398.75,96.4"/>
|
||||
<polygon fill="black" points="398.75,100 400.55,96.4 396.95,96.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="376.25,80 376.25,90.0 51.25,90.0 51.25,96.4"/>
|
||||
<polygon fill="black" points="51.25,100 53.05,96.4 49.45,96.4"/>
|
||||
<rect x="40" y="100" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="51.25,120 51.25,125.0 95.0,125.0 95.0,95.0 116.25,95.0 116.25,96.4"/>
|
||||
<polygon fill="black" points="116.25,100 118.05,96.4 114.45,96.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="73.75,120 73.75,136.4"/>
|
||||
<polygon fill="black" points="73.75,140 75.55,136.4 71.95,136.4"/>
|
||||
<rect x="105" y="100" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="116.25,120 116.25,125.0 160.0,125.0 160.0,95.0 181.25,95.0 181.25,96.4"/>
|
||||
<polygon fill="black" points="181.25,100 183.05,96.4 179.45,96.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="138.75,120 138.75,136.4"/>
|
||||
<polygon fill="black" points="138.75,140 140.55,136.4 136.95,136.4"/>
|
||||
<rect x="170" y="100" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="181.25,120 181.25,125.0 225.0,125.0 225.0,95.0 246.25,95.0 246.25,96.4"/>
|
||||
<polygon fill="black" points="246.25,100 248.05,96.4 244.45,96.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="203.75,120 203.75,136.4"/>
|
||||
<polygon fill="black" points="203.75,140 205.55,136.4 201.95,136.4"/>
|
||||
<rect x="235" y="100" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="246.25,120 246.25,125.0 290.0,125.0 290.0,95.0 311.25,95.0 311.25,96.4"/>
|
||||
<polygon fill="black" points="311.25,100 313.05,96.4 309.45,96.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="268.75,120 268.75,136.4"/>
|
||||
<polygon fill="black" points="268.75,140 270.55,136.4 266.95,136.4"/>
|
||||
<rect x="300" y="100" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="311.25,120 311.25,125.0 355.0,125.0 355.0,95.0 376.25,95.0 376.25,96.4"/>
|
||||
<polygon fill="black" points="376.25,100 378.05,96.4 374.45,96.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="333.75,120 333.75,136.4"/>
|
||||
<polygon fill="black" points="333.75,140 335.55,136.4 331.95,136.4"/>
|
||||
<rect x="365" y="100" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="398.75,120 398.75,136.4"/>
|
||||
<polygon fill="black" points="398.75,140 400.55,136.4 396.95,136.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="376.25,120 376.25,130.0 51.25,130.0 51.25,136.4"/>
|
||||
<polygon fill="black" points="51.25,140 53.05,136.4 49.45,136.4"/>
|
||||
<rect x="40" y="140" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="51.25,160 51.25,165.0 95.0,165.0 95.0,135.0 116.25,135.0 116.25,136.4"/>
|
||||
<polygon fill="black" points="116.25,140 118.05,136.4 114.45,136.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="73.75,160 73.75,176.4"/>
|
||||
<polygon fill="black" points="73.75,180 75.55,176.4 71.95,176.4"/>
|
||||
<rect x="105" y="140" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="116.25,160 116.25,165.0 160.0,165.0 160.0,135.0 181.25,135.0 181.25,136.4"/>
|
||||
<polygon fill="black" points="181.25,140 183.05,136.4 179.45,136.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="138.75,160 138.75,176.4"/>
|
||||
<polygon fill="black" points="138.75,180 140.55,176.4 136.95,176.4"/>
|
||||
<rect x="170" y="140" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="181.25,160 181.25,165.0 225.0,165.0 225.0,135.0 246.25,135.0 246.25,136.4"/>
|
||||
<polygon fill="black" points="246.25,140 248.05,136.4 244.45,136.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="203.75,160 203.75,176.4"/>
|
||||
<polygon fill="black" points="203.75,180 205.55,176.4 201.95,176.4"/>
|
||||
<rect x="235" y="140" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="246.25,160 246.25,165.0 290.0,165.0 290.0,135.0 311.25,135.0 311.25,136.4"/>
|
||||
<polygon fill="black" points="311.25,140 313.05,136.4 309.45,136.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="268.75,160 268.75,176.4"/>
|
||||
<polygon fill="black" points="268.75,180 270.55,176.4 266.95,176.4"/>
|
||||
<rect x="300" y="140" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="311.25,160 311.25,165.0 355.0,165.0 355.0,135.0 376.25,135.0 376.25,136.4"/>
|
||||
<polygon fill="black" points="376.25,140 378.05,136.4 374.45,136.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="333.75,160 333.75,176.4"/>
|
||||
<polygon fill="black" points="333.75,180 335.55,176.4 331.95,176.4"/>
|
||||
<rect x="365" y="140" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="398.75,160 398.75,176.4"/>
|
||||
<polygon fill="black" points="398.75,180 400.55,176.4 396.95,176.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="376.25,160 376.25,170.0 51.25,170.0 51.25,176.4"/>
|
||||
<polygon fill="black" points="51.25,180 53.05,176.4 49.45,176.4"/>
|
||||
<rect x="40" y="180" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="51.25,200 51.25,205.0 95.0,205.0 95.0,175.0 116.25,175.0 116.25,176.4"/>
|
||||
<polygon fill="black" points="116.25,180 118.05,176.4 114.45,176.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="73.75,200 73.75,216.4"/>
|
||||
<polygon fill="black" points="73.75,220 75.55,216.4 71.95,216.4"/>
|
||||
<rect x="105" y="180" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="116.25,200 116.25,205.0 160.0,205.0 160.0,175.0 181.25,175.0 181.25,176.4"/>
|
||||
<polygon fill="black" points="181.25,180 183.05,176.4 179.45,176.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="138.75,200 138.75,216.4"/>
|
||||
<polygon fill="black" points="138.75,220 140.55,216.4 136.95,216.4"/>
|
||||
<rect x="170" y="180" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="181.25,200 181.25,205.0 225.0,205.0 225.0,175.0 246.25,175.0 246.25,176.4"/>
|
||||
<polygon fill="black" points="246.25,180 248.05,176.4 244.45,176.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="203.75,200 203.75,216.4"/>
|
||||
<polygon fill="black" points="203.75,220 205.55,216.4 201.95,216.4"/>
|
||||
<rect x="235" y="180" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="246.25,200 246.25,205.0 290.0,205.0 290.0,175.0 311.25,175.0 311.25,176.4"/>
|
||||
<polygon fill="black" points="311.25,180 313.05,176.4 309.45,176.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="268.75,200 268.75,216.4"/>
|
||||
<polygon fill="black" points="268.75,220 270.55,216.4 266.95,216.4"/>
|
||||
<rect x="300" y="180" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="311.25,200 311.25,205.0 355.0,205.0 355.0,175.0 376.25,175.0 376.25,176.4"/>
|
||||
<polygon fill="black" points="376.25,180 378.05,176.4 374.45,176.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="333.75,200 333.75,216.4"/>
|
||||
<polygon fill="black" points="333.75,220 335.55,216.4 331.95,216.4"/>
|
||||
<rect x="365" y="180" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="398.75,200 398.75,216.4"/>
|
||||
<polygon fill="black" points="398.75,220 400.55,216.4 396.95,216.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="376.25,200 376.25,210.0 51.25,210.0 51.25,216.4"/>
|
||||
<polygon fill="black" points="51.25,220 53.05,216.4 49.45,216.4"/>
|
||||
<rect x="40" y="220" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="51.25,240 51.25,245.0 95.0,245.0 95.0,215.0 116.25,215.0 116.25,216.4"/>
|
||||
<polygon fill="black" points="116.25,220 118.05,216.4 114.45,216.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="73.75,240 73.75,256.4"/>
|
||||
<polygon fill="black" points="73.75,260 75.55,256.4 71.95,256.4"/>
|
||||
<rect x="105" y="220" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="116.25,240 116.25,245.0 160.0,245.0 160.0,215.0 181.25,215.0 181.25,216.4"/>
|
||||
<polygon fill="black" points="181.25,220 183.05,216.4 179.45,216.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="138.75,240 138.75,256.4"/>
|
||||
<polygon fill="black" points="138.75,260 140.55,256.4 136.95,256.4"/>
|
||||
<rect x="170" y="220" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="181.25,240 181.25,245.0 225.0,245.0 225.0,215.0 246.25,215.0 246.25,216.4"/>
|
||||
<polygon fill="black" points="246.25,220 248.05,216.4 244.45,216.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="203.75,240 203.75,256.4"/>
|
||||
<polygon fill="black" points="203.75,260 205.55,256.4 201.95,256.4"/>
|
||||
<rect x="235" y="220" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="246.25,240 246.25,245.0 290.0,245.0 290.0,215.0 311.25,215.0 311.25,216.4"/>
|
||||
<polygon fill="black" points="311.25,220 313.05,216.4 309.45,216.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="268.75,240 268.75,256.4"/>
|
||||
<polygon fill="black" points="268.75,260 270.55,256.4 266.95,256.4"/>
|
||||
<rect x="300" y="220" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="311.25,240 311.25,245.0 355.0,245.0 355.0,215.0 376.25,215.0 376.25,216.4"/>
|
||||
<polygon fill="black" points="376.25,220 378.05,216.4 374.45,216.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="333.75,240 333.75,256.4"/>
|
||||
<polygon fill="black" points="333.75,260 335.55,256.4 331.95,256.4"/>
|
||||
<rect x="365" y="220" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="398.75,240 398.75,256.4"/>
|
||||
<polygon fill="black" points="398.75,260 400.55,256.4 396.95,256.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="376.25,240 376.25,250.0 51.25,250.0 51.25,256.4"/>
|
||||
<polygon fill="black" points="51.25,260 53.05,256.4 49.45,256.4"/>
|
||||
<rect x="40" y="260" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="51.25,280 51.25,285.0 95.0,285.0 95.0,255.0 116.25,255.0 116.25,256.4"/>
|
||||
<polygon fill="black" points="116.25,260 118.05,256.4 114.45,256.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="73.75,280 73.75,296.4"/>
|
||||
<polygon fill="black" points="73.75,300 75.55,296.4 71.95,296.4"/>
|
||||
<rect x="105" y="260" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="116.25,280 116.25,285.0 160.0,285.0 160.0,255.0 181.25,255.0 181.25,256.4"/>
|
||||
<polygon fill="black" points="181.25,260 183.05,256.4 179.45,256.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="138.75,280 138.75,296.4"/>
|
||||
<polygon fill="black" points="138.75,300 140.55,296.4 136.95,296.4"/>
|
||||
<rect x="170" y="260" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="181.25,280 181.25,285.0 225.0,285.0 225.0,255.0 246.25,255.0 246.25,256.4"/>
|
||||
<polygon fill="black" points="246.25,260 248.05,256.4 244.45,256.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="203.75,280 203.75,296.4"/>
|
||||
<polygon fill="black" points="203.75,300 205.55,296.4 201.95,296.4"/>
|
||||
<rect x="235" y="260" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="246.25,280 246.25,285.0 290.0,285.0 290.0,255.0 311.25,255.0 311.25,256.4"/>
|
||||
<polygon fill="black" points="311.25,260 313.05,256.4 309.45,256.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="268.75,280 268.75,296.4"/>
|
||||
<polygon fill="black" points="268.75,300 270.55,296.4 266.95,296.4"/>
|
||||
<rect x="300" y="260" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="311.25,280 311.25,285.0 355.0,285.0 355.0,255.0 376.25,255.0 376.25,256.4"/>
|
||||
<polygon fill="black" points="376.25,260 378.05,256.4 374.45,256.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="333.75,280 333.75,296.4"/>
|
||||
<polygon fill="black" points="333.75,300 335.55,296.4 331.95,296.4"/>
|
||||
<rect x="365" y="260" width="45" height="20" fill="lightblue" stroke="black" stroke-width="1.0"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="398.75,280 398.75,296.4"/>
|
||||
<polygon fill="black" points="398.75,300 400.55,296.4 396.95,296.4"/>
|
||||
<polyline fill="none" stroke="black" stroke_width="2" points="376.25,280 376.25,290.0 51.25,290.0 51.25,296.4"/>
|
||||
<polygon fill="black" points="51.25,300 53.05,296.4 49.45,296.4"/>
|
||||
<text text-anchor="middle" class="label" x="51.25" y="35">IV</text>
|
||||
<text text-anchor="middle" class="label" x="73.75" y="35">m[0]</text>
|
||||
<text text-anchor="middle" class="label" x="138.75" y="35">m[1]</text>
|
||||
<text text-anchor="middle" class="label" x="203.75" y="35">m[2]</text>
|
||||
<text text-anchor="middle" class="label" x="268.75" y="35">m[3]</text>
|
||||
<text text-anchor="middle" class="label" x="333.75" y="35">m[4]</text>
|
||||
<text text-anchor="middle" class="label" x="398.75" y="35">m[5]</text>
|
||||
<text text-anchor="middle" class="label" x="51.25" y="312">c[0]</text>
|
||||
<text text-anchor="middle" class="label" x="73.75" y="312">c[1]</text>
|
||||
<text text-anchor="middle" class="label" x="138.75" y="312">c[2]</text>
|
||||
<text text-anchor="middle" class="label" x="203.75" y="312">c[3]</text>
|
||||
<text text-anchor="middle" class="label" x="268.75" y="312">c[4]</text>
|
||||
<text text-anchor="middle" class="label" x="333.75" y="312">c[5]</text>
|
||||
<text text-anchor="middle" class="label" x="398.75" y="312">c[6]</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 18 KiB |
@@ -4,3 +4,4 @@
|
||||
* [ECDH](ecdh.md)
|
||||
* [Diffie-Hellman](dh.md)
|
||||
* [AES-GCM](aesgcm.md)
|
||||
* [Key-wrap](key_wrap.md)
|
||||
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
# KeyWrap (NIST SP 800 38f)
|
||||
|
||||
# Description
|
||||
|
||||
NIST SP 800 38f describes three keywrap primitives (KW, KWP and TKW). The three
|
||||
primitives are related in that they use the same underlying construction for a
|
||||
strong pseudorandom permutation. KW and KWP use AES, TKW uses DES. The input
|
||||
size of KW and TKW are limited to a multiple of 8 (rsp 4) bytes, KWP adds a
|
||||
padding so that arbitrary length inputs can be processed.
|
||||
|
||||
KW is also defined by [RFC 3394](https://tools.ietf.org/html/rfc3394). KWP is
|
||||
also defined by [RFC 5649](https://tools.ietf.org/html/rfc5649). TKW is a key
|
||||
wrap primitive that uses TripleDES instead of AES.
|
||||
|
||||
All the key wrap primitives use an underlying permutation (called W by NIST),
|
||||
with a structure shown in the diagram below. The primitive consists of 6 rounds,
|
||||
where in each round consecutive an IV and consecutive semiblocks are mixed
|
||||
together using AES (rsp. TripleDES) as block cipher. The design goal appears to
|
||||
be that this permutation is strong pseudorandom. The authors of RFC 3394 speak
|
||||
of an "ideal pseudorandom permutation" without a precise definition.
|
||||
|
||||
{style="display:block;margin:auto"}
|
||||
|
||||
# Padding oracles (KWP)
|
||||
|
||||
Keys wrapped with KWP are padded before the wrapping. The padding of a key K has
|
||||
the following format
|
||||
|
||||
IV || length || Key || pad,
|
||||
|
||||
where IV is the 4 byte constant `0xA65959A6`, length is the length of the key K
|
||||
as a 4 byte bigendian byte array, pad are 0 bytes so that the length of the
|
||||
padded byte array is a multiple of 8 bytes long. Unwrapping requires that the
|
||||
padding is checked and used as an integrity check. The probability that a random
|
||||
string has the padding above is about $$1.004\cdot 2^{-64}$$. Hence checking the
|
||||
padding gives about 64 bit of security against an attacker that tries to pass
|
||||
random inputs as wrapped keys.
|
||||
|
||||
An implementation is expected to check all the parts of the padding. If it
|
||||
throws exceptions depending on which part of the padding is unexpected then
|
||||
these exception leak partial information about the plaintext in form of a
|
||||
padding oracle. Many cryptographic primitives are susceptible to attacks if
|
||||
padding oracles are present. So one question is whether this is the case here
|
||||
too.
|
||||
|
||||
An analysis of cryptographic primitives based on strong pseudorandom
|
||||
permutations is [BR00]. Theorem 2 implies that checking redundancy in the
|
||||
plaintext gives an integrity check is correct, i.e. any constant part in the
|
||||
plaintext is useful as integrity check.
|
||||
|
||||
Another property of strong pseudorandom permutations is that the decryption
|
||||
D(c') of a modified ciphertext c' does not reveal anything useful about D(c). So
|
||||
instead of wondering whether some padding information or side channel is useful
|
||||
for an attacker one can look at the situation where the attacker receives all of
|
||||
D(c') for any modified c'. Strong pseudorandomness implies that this does not
|
||||
help to find D(c). A padding oracle leaks of course less information than the
|
||||
full plaintext D(c'). Hence if the full plaintext is not useful for an attack
|
||||
then a padding oracle is not helpful either.
|
||||
|
||||
So basing a key wrap primitive on a potential strong pseudorandom permutation is
|
||||
a robust approach. Its properties would rule out padding attacks. However, KWP
|
||||
is breaking the strong pseudorandom property. While it uses KW for most of the
|
||||
wrappings and unwrappings, it uses a single AES encryption and decryption for
|
||||
plaintexts of size 8 or smaller. If one tries the same argumentation as above,
|
||||
i.e. allow an attacker to just access D(c') for all modified ciphertexts c' then
|
||||
there is an attack, since the attacker can simply call the decryption oracle
|
||||
multiple times with 16 byte ciphertexts.
|
||||
|
||||
In practice an attacker should only learn partial information about the
|
||||
decrypted ciphertext and hence the attack above is theoretical. But it is still
|
||||
quite puzzling why an RFC would abandon a nice property to encrypt key of sizes
|
||||
(64-bit or less) that shouldn't be used in the first place.
|
||||
|
||||
NIST SP 800 38f allows to restrict the input sizes to key sizes actually used.
|
||||
Today nobody should use 8 byte keys for anything. Hence, it would make sense if
|
||||
any implementation of KWP would disallow keys of size 8 or smaller and hence
|
||||
wrappings of size 16 byte.
|
||||
|
||||
## Cryptanalysis
|
||||
|
||||
### Forgery attack
|
||||
|
||||
NIST SP 800 38f describes a forgery attack by Ferguson. The attack uses a known
|
||||
wrapping of a message that is n semiblocks long. Ferguson observed that there it
|
||||
is possible that modifying the last block of the ciphertext does not propagate
|
||||
to first block of the decryption. In particular, if there exists blocks
|
||||
$$1\leq i_1\leq i_2\leq i_3\leq i_4\leq i_5\leq i_6\leq n,$$ such that the
|
||||
decryption of block $$i_r$$ in round $$r$$ does not change the outcome of the
|
||||
first half of the plaintext then decryption does not change the IV and hence the
|
||||
modified ciphertext is accepted as a valid key wrapping. The probability of this
|
||||
happening is approximately
|
||||
|
||||
$$1/720 (n / 2^h)^6,$$
|
||||
|
||||
where $$n$$ is the number of semiblocks of the message and $$h$$ is the number
|
||||
of bits of a semiblock (i.e. $$h=64$$ for AES). This probability becomes
|
||||
significant if $$n$$ is large.
|
||||
|
||||
### Distinguishing attack
|
||||
|
||||
The forgery attack by
|
||||
Ferguson can also be used for a distinguishing attack. The basic goal of the
|
||||
distinguishing attack is to show that the underlying construction can be
|
||||
distinguished from a random permutation. The attack is a chosen plaintext
|
||||
attack. The attacker choses small integers $$k,p$$ and a large number $$n$$.
|
||||
The chosen plaintexts are chosen as
|
||||
|
||||
k constant semiblocks || p random semiblocks || n constant semiblocks
|
||||
|
||||
The observation as above is that it is possible that for two inputs the
|
||||
difference in the $$k$$ random semiblocks do not change the entire ciphertext.
|
||||
In particular, if there exists blocks $$k+p\leq i_1\leq i_2\leq i_3\leq i_4\leq
|
||||
i_5\leq n + k + p,$$ such that the encryption of block $$i_r$$ in round $$r$$
|
||||
does not change the second half to the result then the semiblocks $$2\ldots
|
||||
k+1$$ of the ciphertexts of the two inputs will be the same. This time
|
||||
collisions only need to happen in 5 rounds, and the probability of this
|
||||
occurring is larger, i.e. approximately
|
||||
|
||||
$$1/120 (n / 2^h)^5.$$
|
||||
|
||||
Additionally this is now a collision attack. If t messages of the form above are
|
||||
wrapped then the probability of 2 of them having the same semiblocks $$2\ldots
|
||||
k+1$$ is about
|
||||
|
||||
$$1/240 (n / 2^h)^5 t^2.$$
|
||||
|
||||
This probability is significant if $$n$$ is large, especially if n is close to
|
||||
$$2^h$$. TKW is the weakest proposal here, because of the small block size of
|
||||
TripleDES. For the maximal allowed input size of $$2^{28}$$ semiblocks an
|
||||
attacker would need about $$2^{14}$$ chosen message for a distinguishing attack.
|
||||
KW and KWP use AES. Because of the larger block size of 128 bits we have
|
||||
$$h=64$$ here. Hence a similar attack requires a lot more chosen plaintexts or
|
||||
much longer plaintexts. E.g. for $$n\leq 2^{32}$$ an attack would require more
|
||||
than $$2^{80}$$ chosen plaintexts, and hence is not feasible.
|
||||
|
||||
For comparison, most encryption primitives based on AES suffer from a birthday
|
||||
attack after significantly less encryptions and in many cases the effect of such
|
||||
an attack is much more devastating. E.g. AES-GCM with random 96-bit IVs likely
|
||||
leaks the authentication key after $$2^{48}$$ encryptions. Extending the attack
|
||||
A distinguishing attack as the one described above is not a huge threat. By
|
||||
itself it does not leak a lot of information. So an open question is whether the
|
||||
distinguishing attack can be extended to a more serious attack. An attacker
|
||||
learns from a collision obtained from a distinguishing attack two partial inputs
|
||||
that produce a collision in the first round. Can this be used somehow?
|
||||
|
||||
## Testing
|
||||
|
||||
Wycheproof has test vectors for KW and KWP (TripleDES variants are ignored). The
|
||||
main focus is on correct wrapping and unwrapping. I.e. the tests assume that the
|
||||
padding of KWP is fully checked: invalid lengths, incorrect IVs or non-zero
|
||||
padding are all rejected. implementations of KW do not wrap messages of size 0,
|
||||
8 or any length not a multiple of 8. For longer inputs the internal counter can
|
||||
overflow. Implementations are expected to implement this correctly or reject
|
||||
longer inputs. Currently the tests do not fail when a padding oracle is present,
|
||||
since such oracles are likely harmless.
|
||||
|
||||
## Reference list
|
||||
|
||||
[BR00]: Bellare, Rogaway, "Encode-Then-Encipher Encryption: How to exploit
|
||||
nonces or redundancy in plaintexts for efficient cryptography", Asiacrypt 2000,
|
||||
pp.317--330.
|
||||
Reference in New Issue
Block a user