From 1563bb41dd64d966ca25387597cd3490271732b3 Mon Sep 17 00:00:00 2001 From: drasko Date: Sun, 14 Apr 2024 15:00:56 +0000 Subject: [PATCH] Deployed 4f40900 with MkDocs version: 1.4.2 --- .nojekyll | 0 404.html | 433 ++ CNAME | 1 + agent/index.html | 546 ++ architecture/index.html | 584 ++ assets/images/favicon.png | Bin 0 -> 1870 bytes assets/javascripts/bundle.51d95adb.min.js | 29 + assets/javascripts/bundle.51d95adb.min.js.map | 8 + assets/javascripts/lunr/min/lunr.ar.min.js | 1 + assets/javascripts/lunr/min/lunr.da.min.js | 18 + assets/javascripts/lunr/min/lunr.de.min.js | 18 + assets/javascripts/lunr/min/lunr.du.min.js | 18 + assets/javascripts/lunr/min/lunr.es.min.js | 18 + assets/javascripts/lunr/min/lunr.fi.min.js | 18 + assets/javascripts/lunr/min/lunr.fr.min.js | 18 + assets/javascripts/lunr/min/lunr.hi.min.js | 1 + assets/javascripts/lunr/min/lunr.hu.min.js | 18 + assets/javascripts/lunr/min/lunr.it.min.js | 18 + assets/javascripts/lunr/min/lunr.ja.min.js | 1 + assets/javascripts/lunr/min/lunr.jp.min.js | 1 + assets/javascripts/lunr/min/lunr.ko.min.js | 1 + assets/javascripts/lunr/min/lunr.multi.min.js | 1 + assets/javascripts/lunr/min/lunr.nl.min.js | 18 + assets/javascripts/lunr/min/lunr.no.min.js | 18 + assets/javascripts/lunr/min/lunr.pt.min.js | 18 + assets/javascripts/lunr/min/lunr.ro.min.js | 18 + assets/javascripts/lunr/min/lunr.ru.min.js | 18 + .../lunr/min/lunr.stemmer.support.min.js | 1 + assets/javascripts/lunr/min/lunr.sv.min.js | 18 + assets/javascripts/lunr/min/lunr.ta.min.js | 1 + assets/javascripts/lunr/min/lunr.th.min.js | 1 + assets/javascripts/lunr/min/lunr.tr.min.js | 18 + assets/javascripts/lunr/min/lunr.vi.min.js | 1 + assets/javascripts/lunr/min/lunr.zh.min.js | 1 + assets/javascripts/lunr/tinyseg.js | 206 + assets/javascripts/lunr/wordcut.js | 6708 +++++++++++++++++ .../workers/search.e5c33ebb.min.js | 42 + .../workers/search.e5c33ebb.min.js.map | 8 + assets/stylesheets/main.558e4712.min.css | 1 + assets/stylesheets/main.558e4712.min.css.map | 1 + assets/stylesheets/palette.2505c338.min.css | 1 + .../stylesheets/palette.2505c338.min.css.map | 1 + attestation/index.html | 556 ++ cli/index.html | 655 ++ computation/index.html | 541 ++ developer-guide/index.html | 862 +++ getting-started/index.html | 710 ++ hal/index.html | 541 ++ img/arch.jpg | Bin 0 -> 49516 bytes img/arch.png | Bin 0 -> 82237 bytes img/atls.png | Bin 0 -> 42272 bytes img/hal.png | Bin 0 -> 36869 bytes index.html | 555 ++ manager/index.html | 899 +++ search/search_index.json | 1 + sitemap.xml | 58 + sitemap.xml.gz | Bin 0 -> 285 bytes tee/index.html | 516 ++ 58 files changed, 14744 insertions(+) create mode 100644 .nojekyll create mode 100644 404.html create mode 100644 CNAME create mode 100644 agent/index.html create mode 100644 architecture/index.html create mode 100644 assets/images/favicon.png create mode 100644 assets/javascripts/bundle.51d95adb.min.js create mode 100644 assets/javascripts/bundle.51d95adb.min.js.map create mode 100644 assets/javascripts/lunr/min/lunr.ar.min.js create mode 100644 assets/javascripts/lunr/min/lunr.da.min.js create mode 100644 assets/javascripts/lunr/min/lunr.de.min.js create mode 100644 assets/javascripts/lunr/min/lunr.du.min.js create mode 100644 assets/javascripts/lunr/min/lunr.es.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hu.min.js create mode 100644 assets/javascripts/lunr/min/lunr.it.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ja.min.js create mode 100644 assets/javascripts/lunr/min/lunr.jp.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ko.min.js create mode 100644 assets/javascripts/lunr/min/lunr.multi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.nl.min.js create mode 100644 assets/javascripts/lunr/min/lunr.no.min.js create mode 100644 assets/javascripts/lunr/min/lunr.pt.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ro.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ru.min.js create mode 100644 assets/javascripts/lunr/min/lunr.stemmer.support.min.js create mode 100644 assets/javascripts/lunr/min/lunr.sv.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ta.min.js create mode 100644 assets/javascripts/lunr/min/lunr.th.min.js create mode 100644 assets/javascripts/lunr/min/lunr.tr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.vi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.zh.min.js create mode 100644 assets/javascripts/lunr/tinyseg.js create mode 100644 assets/javascripts/lunr/wordcut.js create mode 100644 assets/javascripts/workers/search.e5c33ebb.min.js create mode 100644 assets/javascripts/workers/search.e5c33ebb.min.js.map create mode 100644 assets/stylesheets/main.558e4712.min.css create mode 100644 assets/stylesheets/main.558e4712.min.css.map create mode 100644 assets/stylesheets/palette.2505c338.min.css create mode 100644 assets/stylesheets/palette.2505c338.min.css.map create mode 100644 attestation/index.html create mode 100644 cli/index.html create mode 100644 computation/index.html create mode 100644 developer-guide/index.html create mode 100644 getting-started/index.html create mode 100644 hal/index.html create mode 100644 img/arch.jpg create mode 100644 img/arch.png create mode 100644 img/atls.png create mode 100644 img/hal.png create mode 100644 index.html create mode 100644 manager/index.html create mode 100644 search/search_index.json create mode 100644 sitemap.xml create mode 100644 sitemap.xml.gz create mode 100644 tee/index.html diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..0972e2d --- /dev/null +++ b/404.html @@ -0,0 +1,433 @@ + + + + + + + + + + + + + + + + + + + + Cocos + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ +

404 - Not found

+ +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..06916d6 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +docs.cocos.ultraviolet.rs diff --git a/agent/index.html b/agent/index.html new file mode 100644 index 0000000..987a1ea --- /dev/null +++ b/agent/index.html @@ -0,0 +1,546 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Agent - Cocos + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Agent#

+

The agent is responsible for the life cycle of the computation, i.e., running the computation and sending events about the status of the computation within the TEE. The agent is found inside the VM (TEE), and each computation within the TEE has its own agent. When a computation run request is sent from from the manager, manager creates a VM where the agent is found and sends the computation manifest to the agent.

+

Agent Events#

+

As the computation in the agent undergoes different operations, it sends events to the manager so that the user can monitor the computation from either the UI or other client. Events sent to the manager include computation running, computation finished, computation failed, and computation stopped.

+

Vsock Connection Between Agent & Manager#

+

Agent sends agent events to the manager via vsock. The manager listens to the vsock and forwards the events via gRPC. The agent events are used to show the status of the computation inside the TEE so that a user can be aware of what is happening inside the TEE.

+

Security#

+

To run a computation in the agent, a signed certificate is required. The certificate is used to verify the user who is running the computation. The certificate is sent to the agent by the manager, and the agent verifies the certificate before running the computation.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/architecture/index.html b/architecture/index.html new file mode 100644 index 0000000..f008679 --- /dev/null +++ b/architecture/index.html @@ -0,0 +1,584 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Architecture - Cocos + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Architecture#

+

CocosAI system is running on the host, and it's main goal is to enable:

+
    +
  • Programatic creation of enclaves (TEEs)
  • +
  • Gest OS and system enviroment withn the enclave VMs
  • +
  • Monitoring of enclaves
  • +
  • In-enclave SW manager agent
  • +
  • Ectyped data trensfer into the enclave and computation execution
  • +
  • Result retrieval via encrypted channel to an authorized party
  • +
  • Providing of HW measurement and attestation report
  • +
  • Enablement of vTPM and DICE integrity checks (root chain of trust) in order to ensure secure boot of the TEEs
  • +
+

These features are implemented by several independed components of CocosAI system:

+
    +
  1. Manager
  2. +
  3. Agent
  4. +
  5. EOS (Enclave Operating System)
  6. +
  7. CLI
  8. +
+

Cocos Arch

+
+

N.B. CocosAI open-source project does not provide Computation Management service. It is usually a cloud component, used to define a Computation (i.e. define computation metadata, like participant list, algorithm and data providers, result recipients, etc...). Ultraviolet provide commercial product Prism, a multi-party computation platform, that implements multi-tenant and scalable Computation Management service, running in the cloud or on premise, and capable to connect and control CocosAI system running on the TEE host.

+
+

Manager#

+

Manager is a gRPC client that listens to requests sent through gRPC and sends them to Agent via vsock. Manager creates a secure enclave and loads the computation where the agent resides. The connection between Manager and Agent is through vsock, through which channel agent sends events periodically to manager, who forwards these via gRPC.

+

Agent#

+

Agent defines firmware which goes into the TEE and is used to control and monitor computation within TEE and enable secure and encrypted communication with outside world (in order to fetch the data and provide the result of the computation). The Agent contains a gRPC server that listens for requests from gRPC clients. Communication between the Manager and Agent is done via vsock. The Agent sends events to the Manager via vsock, which then forwards these via gRPC. Agent contains a gRPC server that exposes useful functions that can be accessed by other gRPC clients such as the CLI.

+

EOS#

+

EOS, or Enclave Operating System, is ...

+

CLI#

+

CoCoS CLI is used to access the agent within the secure enclave. CLI communicates to agent using gRPC, with funcitons such as algo to provide the algorithm to be run, data to provide the data to be used in the computation, and run to start the computation. It also has functions to fetch and validate the attestation report of the enclave.

+

For more information on CLI, please refer to CLI docs.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..1cf13b9f9d978896599290a74f77d5dbe7d1655c GIT binary patch literal 1870 zcmV-U2eJ5xP)Gc)JR9QMau)O=X#!i9;T z37kk-upj^(fsR36MHs_+1RCI)NNu9}lD0S{B^g8PN?Ww(5|~L#Ng*g{WsqleV}|#l zz8@ri&cTzw_h33bHI+12+kK6WN$h#n5cD8OQt`5kw6p~9H3()bUQ8OS4Q4HTQ=1Ol z_JAocz`fLbT2^{`8n~UAo=#AUOf=SOq4pYkt;XbC&f#7lb$*7=$na!mWCQ`dBQsO0 zLFBSPj*N?#u5&pf2t4XjEGH|=pPQ8xh7tpx;US5Cx_Ju;!O`ya-yF`)b%TEt5>eP1ZX~}sjjA%FJF?h7cX8=b!DZl<6%Cv z*G0uvvU+vmnpLZ2paivG-(cd*y3$hCIcsZcYOGh{$&)A6*XX&kXZd3G8m)G$Zz-LV z^GF3VAW^Mdv!)4OM8EgqRiz~*Cji;uzl2uC9^=8I84vNp;ltJ|q-*uQwGp2ma6cY7 z;`%`!9UXO@fr&Ebapfs34OmS9^u6$)bJxrucutf>`dKPKT%%*d3XlFVKunp9 zasduxjrjs>f8V=D|J=XNZp;_Zy^WgQ$9WDjgY=z@stwiEBm9u5*|34&1Na8BMjjgf3+SHcr`5~>oz1Y?SW^=K z^bTyO6>Gar#P_W2gEMwq)ot3; zREHn~U&Dp0l6YT0&k-wLwYjb?5zGK`W6S2v+K>AM(95m2C20L|3m~rN8dprPr@t)5lsk9Hu*W z?pS990s;Ez=+Rj{x7p``4>+c0G5^pYnB1^!TL=(?HLHZ+HicG{~4F1d^5Awl_2!1jICM-!9eoLhbbT^;yHcefyTAaqRcY zmuctDopPT!%k+}x%lZRKnzykr2}}XfG_ne?nRQO~?%hkzo;@RN{P6o`&mMUWBYMTe z6i8ChtjX&gXl`nvrU>jah)2iNM%JdjqoaeaU%yVn!^70x-flljp6Q5tK}5}&X8&&G zX3fpb3E(!rH=zVI_9Gjl45w@{(ITqngWFe7@9{mX;tO25Z_8 zQHEpI+FkTU#4xu>RkN>b3Tnc3UpWzPXWm#o55GKF09j^Mh~)K7{QqbO_~(@CVq! zS<8954|P8mXN2MRs86xZ&Q4EfM@JB94b=(YGuk)s&^jiSF=t3*oNK3`rD{H`yQ?d; ztE=laAUoZx5?RC8*WKOj`%LXEkgDd>&^Q4M^z`%u0rg-It=hLCVsq!Z%^6eB-OvOT zFZ28TN&cRmgU}Elrnk43)!>Z1FCPL2K$7}gwzIc48NX}#!A1BpJP?#v5wkNprhV** z?Cpalt1oH&{r!o3eSKc&ap)iz2BTn_VV`4>9M^b3;(YY}4>#ML6{~(4mH+?%07*qo IM6N<$f(jP3KmY&$ literal 0 HcmV?d00001 diff --git a/assets/javascripts/bundle.51d95adb.min.js b/assets/javascripts/bundle.51d95adb.min.js new file mode 100644 index 0000000..b20ec68 --- /dev/null +++ b/assets/javascripts/bundle.51d95adb.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var Hi=Object.create;var xr=Object.defineProperty;var Pi=Object.getOwnPropertyDescriptor;var $i=Object.getOwnPropertyNames,kt=Object.getOwnPropertySymbols,Ii=Object.getPrototypeOf,Er=Object.prototype.hasOwnProperty,an=Object.prototype.propertyIsEnumerable;var on=(e,t,r)=>t in e?xr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,P=(e,t)=>{for(var r in t||(t={}))Er.call(t,r)&&on(e,r,t[r]);if(kt)for(var r of kt(t))an.call(t,r)&&on(e,r,t[r]);return e};var sn=(e,t)=>{var r={};for(var n in e)Er.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&kt)for(var n of kt(e))t.indexOf(n)<0&&an.call(e,n)&&(r[n]=e[n]);return r};var Ht=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Fi=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of $i(t))!Er.call(e,o)&&o!==r&&xr(e,o,{get:()=>t[o],enumerable:!(n=Pi(t,o))||n.enumerable});return e};var yt=(e,t,r)=>(r=e!=null?Hi(Ii(e)):{},Fi(t||!e||!e.__esModule?xr(r,"default",{value:e,enumerable:!0}):r,e));var fn=Ht((wr,cn)=>{(function(e,t){typeof wr=="object"&&typeof cn!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(wr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,a={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function s(T){return!!(T&&T!==document&&T.nodeName!=="HTML"&&T.nodeName!=="BODY"&&"classList"in T&&"contains"in T.classList)}function f(T){var Ke=T.type,We=T.tagName;return!!(We==="INPUT"&&a[Ke]&&!T.readOnly||We==="TEXTAREA"&&!T.readOnly||T.isContentEditable)}function c(T){T.classList.contains("focus-visible")||(T.classList.add("focus-visible"),T.setAttribute("data-focus-visible-added",""))}function u(T){T.hasAttribute("data-focus-visible-added")&&(T.classList.remove("focus-visible"),T.removeAttribute("data-focus-visible-added"))}function p(T){T.metaKey||T.altKey||T.ctrlKey||(s(r.activeElement)&&c(r.activeElement),n=!0)}function m(T){n=!1}function d(T){s(T.target)&&(n||f(T.target))&&c(T.target)}function h(T){s(T.target)&&(T.target.classList.contains("focus-visible")||T.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(T.target))}function v(T){document.visibilityState==="hidden"&&(o&&(n=!0),B())}function B(){document.addEventListener("mousemove",z),document.addEventListener("mousedown",z),document.addEventListener("mouseup",z),document.addEventListener("pointermove",z),document.addEventListener("pointerdown",z),document.addEventListener("pointerup",z),document.addEventListener("touchmove",z),document.addEventListener("touchstart",z),document.addEventListener("touchend",z)}function re(){document.removeEventListener("mousemove",z),document.removeEventListener("mousedown",z),document.removeEventListener("mouseup",z),document.removeEventListener("pointermove",z),document.removeEventListener("pointerdown",z),document.removeEventListener("pointerup",z),document.removeEventListener("touchmove",z),document.removeEventListener("touchstart",z),document.removeEventListener("touchend",z)}function z(T){T.target.nodeName&&T.target.nodeName.toLowerCase()==="html"||(n=!1,re())}document.addEventListener("keydown",p,!0),document.addEventListener("mousedown",m,!0),document.addEventListener("pointerdown",m,!0),document.addEventListener("touchstart",m,!0),document.addEventListener("visibilitychange",v,!0),B(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var un=Ht(Sr=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(c){return!1}},r=t(),n=function(c){var u={next:function(){var p=c.shift();return{done:p===void 0,value:p}}};return r&&(u[Symbol.iterator]=function(){return u}),u},o=function(c){return encodeURIComponent(c).replace(/%20/g,"+")},i=function(c){return decodeURIComponent(String(c).replace(/\+/g," "))},a=function(){var c=function(p){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var m=typeof p;if(m!=="undefined")if(m==="string")p!==""&&this._fromString(p);else if(p instanceof c){var d=this;p.forEach(function(re,z){d.append(z,re)})}else if(p!==null&&m==="object")if(Object.prototype.toString.call(p)==="[object Array]")for(var h=0;hd[0]?1:0}),c._entries&&(c._entries={});for(var p=0;p1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Sr);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(f,c){typeof f!="string"&&(f=String(f)),c&&typeof c!="string"&&(c=String(c));var u=document,p;if(c&&(e.location===void 0||c!==e.location.href)){c=c.toLowerCase(),u=document.implementation.createHTMLDocument(""),p=u.createElement("base"),p.href=c,u.head.appendChild(p);try{if(p.href.indexOf(c)!==0)throw new Error(p.href)}catch(T){throw new Error("URL unable to set base "+c+" due to "+T)}}var m=u.createElement("a");m.href=f,p&&(u.body.appendChild(m),m.href=m.href);var d=u.createElement("input");if(d.type="url",d.value=f,m.protocol===":"||!/:/.test(m.href)||!d.checkValidity()&&!c)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:m});var h=new e.URLSearchParams(this.search),v=!0,B=!0,re=this;["append","delete","set"].forEach(function(T){var Ke=h[T];h[T]=function(){Ke.apply(h,arguments),v&&(B=!1,re.search=h.toString(),B=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var z=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==z&&(z=this.search,B&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},a=i.prototype,s=function(f){Object.defineProperty(a,f,{get:function(){return this._anchorElement[f]},set:function(c){this._anchorElement[f]=c},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(f){s(f)}),Object.defineProperty(a,"search",{get:function(){return this._anchorElement.search},set:function(f){this._anchorElement.search=f,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(a,{toString:{get:function(){var f=this;return function(){return f.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(f){this._anchorElement.href=f,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(f){this._anchorElement.pathname=f},enumerable:!0},origin:{get:function(){var f={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],c=this._anchorElement.port!=f&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(c?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(f){},enumerable:!0},username:{get:function(){return""},set:function(f){},enumerable:!0}}),i.createObjectURL=function(f){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(f){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Sr)});var Qr=Ht((Lt,Kr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Lt=="object"&&typeof Kr=="object"?Kr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Lt=="object"?Lt.ClipboardJS=r():t.ClipboardJS=r()})(Lt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return ki}});var a=i(279),s=i.n(a),f=i(370),c=i.n(f),u=i(817),p=i.n(u);function m(j){try{return document.execCommand(j)}catch(O){return!1}}var d=function(O){var w=p()(O);return m("cut"),w},h=d;function v(j){var O=document.documentElement.getAttribute("dir")==="rtl",w=document.createElement("textarea");w.style.fontSize="12pt",w.style.border="0",w.style.padding="0",w.style.margin="0",w.style.position="absolute",w.style[O?"right":"left"]="-9999px";var k=window.pageYOffset||document.documentElement.scrollTop;return w.style.top="".concat(k,"px"),w.setAttribute("readonly",""),w.value=j,w}var B=function(O,w){var k=v(O);w.container.appendChild(k);var F=p()(k);return m("copy"),k.remove(),F},re=function(O){var w=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},k="";return typeof O=="string"?k=B(O,w):O instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(O==null?void 0:O.type)?k=B(O.value,w):(k=p()(O),m("copy")),k},z=re;function T(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?T=function(w){return typeof w}:T=function(w){return w&&typeof Symbol=="function"&&w.constructor===Symbol&&w!==Symbol.prototype?"symbol":typeof w},T(j)}var Ke=function(){var O=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},w=O.action,k=w===void 0?"copy":w,F=O.container,q=O.target,Le=O.text;if(k!=="copy"&&k!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&T(q)==="object"&&q.nodeType===1){if(k==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(k==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Le)return z(Le,{container:F});if(q)return k==="cut"?h(q):z(q,{container:F})},We=Ke;function Ie(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Ie=function(w){return typeof w}:Ie=function(w){return w&&typeof Symbol=="function"&&w.constructor===Symbol&&w!==Symbol.prototype?"symbol":typeof w},Ie(j)}function Ti(j,O){if(!(j instanceof O))throw new TypeError("Cannot call a class as a function")}function nn(j,O){for(var w=0;w0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof F.action=="function"?F.action:this.defaultAction,this.target=typeof F.target=="function"?F.target:this.defaultTarget,this.text=typeof F.text=="function"?F.text:this.defaultText,this.container=Ie(F.container)==="object"?F.container:document.body}},{key:"listenClick",value:function(F){var q=this;this.listener=c()(F,"click",function(Le){return q.onClick(Le)})}},{key:"onClick",value:function(F){var q=F.delegateTarget||F.currentTarget,Le=this.action(q)||"copy",Rt=We({action:Le,container:this.container,target:this.target(q),text:this.text(q)});this.emit(Rt?"success":"error",{action:Le,text:Rt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(F){return yr("action",F)}},{key:"defaultTarget",value:function(F){var q=yr("target",F);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(F){return yr("text",F)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(F){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return z(F,q)}},{key:"cut",value:function(F){return h(F)}},{key:"isSupported",value:function(){var F=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof F=="string"?[F]:F,Le=!!document.queryCommandSupported;return q.forEach(function(Rt){Le=Le&&!!document.queryCommandSupported(Rt)}),Le}}]),w}(s()),ki=Ri},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function a(s,f){for(;s&&s.nodeType!==o;){if(typeof s.matches=="function"&&s.matches(f))return s;s=s.parentNode}}n.exports=a},438:function(n,o,i){var a=i(828);function s(u,p,m,d,h){var v=c.apply(this,arguments);return u.addEventListener(m,v,h),{destroy:function(){u.removeEventListener(m,v,h)}}}function f(u,p,m,d,h){return typeof u.addEventListener=="function"?s.apply(null,arguments):typeof m=="function"?s.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return s(v,p,m,d,h)}))}function c(u,p,m,d){return function(h){h.delegateTarget=a(h.target,p),h.delegateTarget&&d.call(u,h)}}n.exports=f},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var a=Object.prototype.toString.call(i);return i!==void 0&&(a==="[object NodeList]"||a==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var a=Object.prototype.toString.call(i);return a==="[object Function]"}},370:function(n,o,i){var a=i(879),s=i(438);function f(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!a.string(d))throw new TypeError("Second argument must be a String");if(!a.fn(h))throw new TypeError("Third argument must be a Function");if(a.node(m))return c(m,d,h);if(a.nodeList(m))return u(m,d,h);if(a.string(m))return p(m,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(m,d,h){return m.addEventListener(d,h),{destroy:function(){m.removeEventListener(d,h)}}}function u(m,d,h){return Array.prototype.forEach.call(m,function(v){v.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(m,function(v){v.removeEventListener(d,h)})}}}function p(m,d,h){return s(document.body,m,d,h)}n.exports=f},817:function(n){function o(i){var a;if(i.nodeName==="SELECT")i.focus(),a=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var s=i.hasAttribute("readonly");s||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),s||i.removeAttribute("readonly"),a=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var f=window.getSelection(),c=document.createRange();c.selectNodeContents(i),f.removeAllRanges(),f.addRange(c),a=f.toString()}return a}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,a,s){var f=this.e||(this.e={});return(f[i]||(f[i]=[])).push({fn:a,ctx:s}),this},once:function(i,a,s){var f=this;function c(){f.off(i,c),a.apply(s,arguments)}return c._=a,this.on(i,c,s)},emit:function(i){var a=[].slice.call(arguments,1),s=((this.e||(this.e={}))[i]||[]).slice(),f=0,c=s.length;for(f;f{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var is=/["'&<>]/;Jo.exports=as;function as(e){var t=""+e,r=is.exec(t);if(!r)return t;var n,o="",i=0,a=0;for(i=r.index;i0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function W(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var n=r.call(e),o,i=[],a;try{for(;(t===void 0||t-- >0)&&!(o=n.next()).done;)i.push(o.value)}catch(s){a={error:s}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(a)throw a.error}}return i}function D(e,t,r){if(r||arguments.length===2)for(var n=0,o=t.length,i;n1||s(m,d)})})}function s(m,d){try{f(n[m](d))}catch(h){p(i[0][3],h)}}function f(m){m.value instanceof Xe?Promise.resolve(m.value.v).then(c,u):p(i[0][2],m)}function c(m){s("next",m)}function u(m){s("throw",m)}function p(m,d){m(d),i.shift(),i.length&&s(i[0][0],i[0][1])}}function mn(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof xe=="function"?xe(e):e[Symbol.iterator](),r={},n("next"),n("throw"),n("return"),r[Symbol.asyncIterator]=function(){return this},r);function n(i){r[i]=e[i]&&function(a){return new Promise(function(s,f){a=e[i](a),o(s,f,a.done,a.value)})}}function o(i,a,s,f){Promise.resolve(f).then(function(c){i({value:c,done:s})},a)}}function A(e){return typeof e=="function"}function at(e){var t=function(n){Error.call(n),n.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var $t=at(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(n,o){return o+1+") "+n.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function De(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Fe=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,n,o,i;if(!this.closed){this.closed=!0;var a=this._parentage;if(a)if(this._parentage=null,Array.isArray(a))try{for(var s=xe(a),f=s.next();!f.done;f=s.next()){var c=f.value;c.remove(this)}}catch(v){t={error:v}}finally{try{f&&!f.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}else a.remove(this);var u=this.initialTeardown;if(A(u))try{u()}catch(v){i=v instanceof $t?v.errors:[v]}var p=this._finalizers;if(p){this._finalizers=null;try{for(var m=xe(p),d=m.next();!d.done;d=m.next()){var h=d.value;try{dn(h)}catch(v){i=i!=null?i:[],v instanceof $t?i=D(D([],W(i)),W(v.errors)):i.push(v)}}}catch(v){n={error:v}}finally{try{d&&!d.done&&(o=m.return)&&o.call(m)}finally{if(n)throw n.error}}}if(i)throw new $t(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)dn(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&De(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&De(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Or=Fe.EMPTY;function It(e){return e instanceof Fe||e&&"closed"in e&&A(e.remove)&&A(e.add)&&A(e.unsubscribe)}function dn(e){A(e)?e():e.unsubscribe()}var Ae={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var st={setTimeout:function(e,t){for(var r=[],n=2;n0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var n=this,o=this,i=o.hasError,a=o.isStopped,s=o.observers;return i||a?Or:(this.currentObservers=null,s.push(r),new Fe(function(){n.currentObservers=null,De(s,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,a=n.isStopped;o?r.error(i):a&&r.complete()},t.prototype.asObservable=function(){var r=new U;return r.source=this,r},t.create=function(r,n){return new wn(r,n)},t}(U);var wn=function(e){ne(t,e);function t(r,n){var o=e.call(this)||this;return o.destination=r,o.source=n,o}return t.prototype.next=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.next)===null||o===void 0||o.call(n,r)},t.prototype.error=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.error)===null||o===void 0||o.call(n,r)},t.prototype.complete=function(){var r,n;(n=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||n===void 0||n.call(r)},t.prototype._subscribe=function(r){var n,o;return(o=(n=this.source)===null||n===void 0?void 0:n.subscribe(r))!==null&&o!==void 0?o:Or},t}(E);var Et={now:function(){return(Et.delegate||Date).now()},delegate:void 0};var wt=function(e){ne(t,e);function t(r,n,o){r===void 0&&(r=1/0),n===void 0&&(n=1/0),o===void 0&&(o=Et);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=n,i._timestampProvider=o,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=n===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,n),i}return t.prototype.next=function(r){var n=this,o=n.isStopped,i=n._buffer,a=n._infiniteTimeWindow,s=n._timestampProvider,f=n._windowTime;o||(i.push(r),!a&&i.push(s.now()+f)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var n=this._innerSubscribe(r),o=this,i=o._infiniteTimeWindow,a=o._buffer,s=a.slice(),f=0;f0?e.prototype.requestAsyncId.call(this,r,n,o):(r.actions.push(this),r._scheduled||(r._scheduled=ut.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,n,o){var i;if(o===void 0&&(o=0),o!=null?o>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,n,o);var a=r.actions;n!=null&&((i=a[a.length-1])===null||i===void 0?void 0:i.id)!==n&&(ut.cancelAnimationFrame(n),r._scheduled=void 0)},t}(Ut);var On=function(e){ne(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var n=this._scheduled;this._scheduled=void 0;var o=this.actions,i;r=r||o.shift();do if(i=r.execute(r.state,r.delay))break;while((r=o[0])&&r.id===n&&o.shift());if(this._active=!1,i){for(;(r=o[0])&&r.id===n&&o.shift();)r.unsubscribe();throw i}},t}(Wt);var we=new On(Tn);var R=new U(function(e){return e.complete()});function Dt(e){return e&&A(e.schedule)}function kr(e){return e[e.length-1]}function Qe(e){return A(kr(e))?e.pop():void 0}function Se(e){return Dt(kr(e))?e.pop():void 0}function Vt(e,t){return typeof kr(e)=="number"?e.pop():t}var pt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function zt(e){return A(e==null?void 0:e.then)}function Nt(e){return A(e[ft])}function qt(e){return Symbol.asyncIterator&&A(e==null?void 0:e[Symbol.asyncIterator])}function Kt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Ki(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Qt=Ki();function Yt(e){return A(e==null?void 0:e[Qt])}function Gt(e){return ln(this,arguments,function(){var r,n,o,i;return Pt(this,function(a){switch(a.label){case 0:r=e.getReader(),a.label=1;case 1:a.trys.push([1,,9,10]),a.label=2;case 2:return[4,Xe(r.read())];case 3:return n=a.sent(),o=n.value,i=n.done,i?[4,Xe(void 0)]:[3,5];case 4:return[2,a.sent()];case 5:return[4,Xe(o)];case 6:return[4,a.sent()];case 7:return a.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function Bt(e){return A(e==null?void 0:e.getReader)}function $(e){if(e instanceof U)return e;if(e!=null){if(Nt(e))return Qi(e);if(pt(e))return Yi(e);if(zt(e))return Gi(e);if(qt(e))return _n(e);if(Yt(e))return Bi(e);if(Bt(e))return Ji(e)}throw Kt(e)}function Qi(e){return new U(function(t){var r=e[ft]();if(A(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function Yi(e){return new U(function(t){for(var r=0;r=2;return function(n){return n.pipe(e?_(function(o,i){return e(o,i,n)}):me,Oe(1),r?He(t):zn(function(){return new Xt}))}}function Nn(){for(var e=[],t=0;t=2,!0))}function fe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new E}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,a=i===void 0?!0:i,s=e.resetOnRefCountZero,f=s===void 0?!0:s;return function(c){var u,p,m,d=0,h=!1,v=!1,B=function(){p==null||p.unsubscribe(),p=void 0},re=function(){B(),u=m=void 0,h=v=!1},z=function(){var T=u;re(),T==null||T.unsubscribe()};return g(function(T,Ke){d++,!v&&!h&&B();var We=m=m!=null?m:r();Ke.add(function(){d--,d===0&&!v&&!h&&(p=jr(z,f))}),We.subscribe(Ke),!u&&d>0&&(u=new et({next:function(Ie){return We.next(Ie)},error:function(Ie){v=!0,B(),p=jr(re,o,Ie),We.error(Ie)},complete:function(){h=!0,B(),p=jr(re,a),We.complete()}}),$(T).subscribe(u))})(c)}}function jr(e,t){for(var r=[],n=2;ne.next(document)),e}function K(e,t=document){return Array.from(t.querySelectorAll(e))}function V(e,t=document){let r=se(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function se(e,t=document){return t.querySelector(e)||void 0}function _e(){return document.activeElement instanceof HTMLElement&&document.activeElement||void 0}function tr(e){return L(b(document.body,"focusin"),b(document.body,"focusout")).pipe(ke(1),l(()=>{let t=_e();return typeof t!="undefined"?e.contains(t):!1}),N(e===_e()),Y())}function Be(e){return{x:e.offsetLeft,y:e.offsetTop}}function Yn(e){return L(b(window,"load"),b(window,"resize")).pipe(Ce(0,we),l(()=>Be(e)),N(Be(e)))}function rr(e){return{x:e.scrollLeft,y:e.scrollTop}}function dt(e){return L(b(e,"scroll"),b(window,"resize")).pipe(Ce(0,we),l(()=>rr(e)),N(rr(e)))}var Bn=function(){if(typeof Map!="undefined")return Map;function e(t,r){var n=-1;return t.some(function(o,i){return o[0]===r?(n=i,!0):!1}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var n=e(this.__entries__,r),o=this.__entries__[n];return o&&o[1]},t.prototype.set=function(r,n){var o=e(this.__entries__,r);~o?this.__entries__[o][1]=n:this.__entries__.push([r,n])},t.prototype.delete=function(r){var n=this.__entries__,o=e(n,r);~o&&n.splice(o,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,n){n===void 0&&(n=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!zr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),xa?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!zr||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,n=r===void 0?"":r,o=ya.some(function(i){return!!~n.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),Jn=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Zn=typeof WeakMap!="undefined"?new WeakMap:new Bn,eo=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=Ea.getInstance(),n=new Ra(t,r,this);Zn.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){eo.prototype[e]=function(){var t;return(t=Zn.get(this))[e].apply(t,arguments)}});var ka=function(){return typeof nr.ResizeObserver!="undefined"?nr.ResizeObserver:eo}(),to=ka;var ro=new E,Ha=I(()=>H(new to(e=>{for(let t of e)ro.next(t)}))).pipe(x(e=>L(Te,H(e)).pipe(C(()=>e.disconnect()))),J(1));function de(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ge(e){return Ha.pipe(S(t=>t.observe(e)),x(t=>ro.pipe(_(({target:r})=>r===e),C(()=>t.unobserve(e)),l(()=>de(e)))),N(de(e)))}function bt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function ar(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var no=new E,Pa=I(()=>H(new IntersectionObserver(e=>{for(let t of e)no.next(t)},{threshold:0}))).pipe(x(e=>L(Te,H(e)).pipe(C(()=>e.disconnect()))),J(1));function sr(e){return Pa.pipe(S(t=>t.observe(e)),x(t=>no.pipe(_(({target:r})=>r===e),C(()=>t.unobserve(e)),l(({isIntersecting:r})=>r))))}function oo(e,t=16){return dt(e).pipe(l(({y:r})=>{let n=de(e),o=bt(e);return r>=o.height-n.height-t}),Y())}var cr={drawer:V("[data-md-toggle=drawer]"),search:V("[data-md-toggle=search]")};function io(e){return cr[e].checked}function qe(e,t){cr[e].checked!==t&&cr[e].click()}function je(e){let t=cr[e];return b(t,"change").pipe(l(()=>t.checked),N(t.checked))}function $a(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ia(){return L(b(window,"compositionstart").pipe(l(()=>!0)),b(window,"compositionend").pipe(l(()=>!1))).pipe(N(!1))}function ao(){let e=b(window,"keydown").pipe(_(t=>!(t.metaKey||t.ctrlKey)),l(t=>({mode:io("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),_(({mode:t,type:r})=>{if(t==="global"){let n=_e();if(typeof n!="undefined")return!$a(n,r)}return!0}),fe());return Ia().pipe(x(t=>t?R:e))}function Me(){return new URL(location.href)}function ot(e){location.href=e.href}function so(){return new E}function co(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)co(e,r)}function M(e,t,...r){let n=document.createElement(e);if(t)for(let o of Object.keys(t))typeof t[o]!="undefined"&&(typeof t[o]!="boolean"?n.setAttribute(o,t[o]):n.setAttribute(o,""));for(let o of r)co(n,o);return n}function fr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function fo(){return location.hash.substring(1)}function uo(e){let t=M("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Fa(){return b(window,"hashchange").pipe(l(fo),N(fo()),_(e=>e.length>0),J(1))}function po(){return Fa().pipe(l(e=>se(`[id="${e}"]`)),_(e=>typeof e!="undefined"))}function Nr(e){let t=matchMedia(e);return Zt(r=>t.addListener(()=>r(t.matches))).pipe(N(t.matches))}function lo(){let e=matchMedia("print");return L(b(window,"beforeprint").pipe(l(()=>!0)),b(window,"afterprint").pipe(l(()=>!1))).pipe(N(e.matches))}function qr(e,t){return e.pipe(x(r=>r?t():R))}function ur(e,t={credentials:"same-origin"}){return ve(fetch(`${e}`,t)).pipe(ce(()=>R),x(r=>r.status!==200?Tt(()=>new Error(r.statusText)):H(r)))}function Ue(e,t){return ur(e,t).pipe(x(r=>r.json()),J(1))}function mo(e,t){let r=new DOMParser;return ur(e,t).pipe(x(n=>n.text()),l(n=>r.parseFromString(n,"text/xml")),J(1))}function pr(e){let t=M("script",{src:e});return I(()=>(document.head.appendChild(t),L(b(t,"load"),b(t,"error").pipe(x(()=>Tt(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(l(()=>{}),C(()=>document.head.removeChild(t)),Oe(1))))}function ho(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function bo(){return L(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(l(ho),N(ho()))}function vo(){return{width:innerWidth,height:innerHeight}}function go(){return b(window,"resize",{passive:!0}).pipe(l(vo),N(vo()))}function yo(){return Q([bo(),go()]).pipe(l(([e,t])=>({offset:e,size:t})),J(1))}function lr(e,{viewport$:t,header$:r}){let n=t.pipe(X("size")),o=Q([n,r]).pipe(l(()=>Be(e)));return Q([r,t,o]).pipe(l(([{height:i},{offset:a,size:s},{x:f,y:c}])=>({offset:{x:a.x-f,y:a.y-c+i},size:s})))}(()=>{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(a=>{let s=document.createElement("script");s.src=i,s.onload=a,document.body.appendChild(s)})),Promise.resolve())}var r=class{constructor(n){this.url=n,this.onerror=null,this.onmessage=null,this.onmessageerror=null,this.m=a=>{a.source===this.w&&(a.stopImmediatePropagation(),this.dispatchEvent(new MessageEvent("message",{data:a.data})),this.onmessage&&this.onmessage(a))},this.e=(a,s,f,c,u)=>{if(s===this.url.toString()){let p=new ErrorEvent("error",{message:a,filename:s,lineno:f,colno:c,error:u});this.dispatchEvent(p),this.onerror&&this.onerror(p)}};let o=new EventTarget;this.addEventListener=o.addEventListener.bind(o),this.removeEventListener=o.removeEventListener.bind(o),this.dispatchEvent=o.dispatchEvent.bind(o);let i=document.createElement("iframe");i.width=i.height=i.frameBorder="0",document.body.appendChild(this.iframe=i),this.w.document.open(),this.w.document.write(` + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Attestation#

+

Remote attestation is a process in which one side (the attester) collects information about itself and sends that information to the client (or the relying party) so that the relying party can verify the attester. The successful verification proves to the relying party that the secure virtual machine (SVM) runs the expected code on the expected hardware and is configured correctly. If the attester is deemed trustworthy, the relying party will send confidential code/data to the attester. This information implies that a secure channel needs to be formed between the attester and the relaying party. The secure channel is created using attested TLS.

+

Cocos has two software components that represent the attester and the relying party:

+
    +
  1. The Agent - software application that is running inside the HAL. It is responsible for fetching the attestation report and running the computation.
  2. +
  3. Cocos CLI - a command-line application running on the machines of each Secure Multiparty Computation (SMPC) member. It verifies the attestation report and sends confidential code/data to the Agent.
  4. +
+

What are the parts of the attestation report?#

+

One of the essential parts of the attestation report is the measurement. The measurement represents the hash of the entire SVM or the hash of the HAL. This way, the measurement provides a way for the client to verify the contents of the entire SVM.

+

Along with the measurement, the attestation report provides additional information about the booted SVM and underlying hardware, such as the policy with which the SVM was booted and the SNP firmware's trusted computing base (TCB) version.

+

The AMD SEV-SNP attestation report can also be filled with arbitrary data. The width of this data field is 512 bits, and it is called report data. The report data content is provided by the Agent to the ASP every time the attestation report is generated.

+

The last part of the report is the signature. The hardware signs the AMD SEV-SNP attestation report using the Versioned Chip Endorsement Key (VCEK). VCEK is derived from chip unique secrets and the current SNP firmware TCB. The signature is verified by obtaining the certificate for the VCEK from the AMD Key Distribution System (KDS). By verifying the signature, the relying party can be sure that the SVM is running on genuine AMD hardware and that the AMD Secure Processor (ASP) generated the attestation report.

+

How is the attestation report fetched?#

+

The Agent is responsible for fetching the attestation report from the SVM. This procedure is safe because the Kernel and the ASP can exchange encrypted messages that can only be decrypted by the Kernel and the ASP. The keys used for the encryption/decryption are inserted by the ASP into the memory of the SVM during boot, thus ensuring that only the ASP and the SVM have the keys for safe communication.

+

Attested TLS#

+

For the relying party to send confidential data or code to the Agent, a secure channel must be established between them. This is done using attested TLS, which is a TLS connection where the server's certificate is extended with the attestation report. The SVM is the server in Cocos. The Agent generates a self-signed x.509 certificate extended with the attestation report. When fetching the attestation report, the Agent inserts the hash of the public key into it using the field report data. The whole process can be seen in the below picture. The green color represents the trusted part of the system, while the red is untrusted.

+

Attested TLS

+

The relying party uses the Cocos CLI to verify the self-signed certificate and the attestation report that is part of it. Successful verification proves to the relying party that the certificate is generated inside the SVM because the certificate's public key is part of the attestation report.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/cli/index.html b/cli/index.html new file mode 100644 index 0000000..69da074 --- /dev/null +++ b/cli/index.html @@ -0,0 +1,655 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + CLI - Cocos + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Agent CLI#

+

The CLI allows you to perform various tasks related to the computation and management of algorithms and datasets. The CLI is a gRPC client for the agent service.

+

Build#

+

To build the CLI, follow these steps:

+
    +
  1. Clone the repository: go get github.com/ultravioletrs/cocos.
  2. +
  3. Navigate to the project root: cd cocos.
  4. +
  5. Build the CLI binary: make cli.
  6. +
+

Usage#

+

Set Agent URL#

+
export AGENT_GRPC_URL=<agent_host:agent_host>
+
+

Upload Algorithm#

+

To upload an algorithm, use the following command:

+
./build/cocos-cli algo /path/to/algorithm
+
+

Upload Dataset#

+

To upload a dataset, use the following command:

+
./build/cocos-cli data /path/to/dataset.csv
+
+

Retrieve Result#

+

To retrieve the computation result, use the following command:

+
./build/cocos-cli result
+
+

Installation#

+

To install the CLI locally, i.e. for the current user:

+

Run make install-cli.

+

Notes#

+
    +
  • The CLI supports various configuration flags and options
  • +
  • Use the --help flag with any command to see additionalinformation
  • +
  • The CLI uses gRPC for communication with the Agent service
  • +
  • All traffic between CLI and the TEE is encrypted via mutual TLS
  • +
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/computation/index.html b/computation/index.html new file mode 100644 index 0000000..e7de5df --- /dev/null +++ b/computation/index.html @@ -0,0 +1,541 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Computation - Cocos + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Computation#

+

Computation in CocosAI is any execution of a program (Algorithm) or an data set (Data), that can be one data file, or a lot of files comping from different parties.

+

Computations are multi-party, meaning that program and data providers can be different parties that do not want to expose their intellectual property to other parties participating in the computation.

+

Computation is a structure that holds all the necessary information needed to execute the computation securely (list of participants, execution backend - i.e. where computation will be executed, role of each participant, cryptographic certificates, etc...).

+

Computation Roles#

+

Computation is multi-party, i.e. has multiple participants. Each of the users that participate in the computation can have one of the follwoing roles:

+
    +
  1. Computation Owner - user that created the Computation and that defines who will participate in it and with wich role (by inviting other users to the Computation)
  2. +
  3. Algorithm Provider - user that will provide th actual program to be executed
  4. +
  5. Data Provider - user that will provide a data on which algorithm will be executed, i.e. data which algorithm will process
  6. +
  7. Result Recipient - user that will recieve result after the processing
  8. +
+

One user can have several roles - for example, Algorithm Provider can also be a Result Recipient.

+

Computation Manifest#

+

Computation Manifest represent that Computation description and is sent upon run command to the Manager as a JSON.

+

Manager fetches the Computation Manifest and sends it into the TEE to Agent, via vsock.

+

The first thing that Agent does upon boot, is that it fetches the Computation Manifest and reads it. For this Manifest, Agent understands who are the participants in the computation adn with wich role, i.e. from whom it can accept the connections and what data they will send. Agent also learns from the Manifest what algorithm is used and how many datasets will be provided. This way it knows when it received all necessary files to start the execution. Finally, Agent learns from the Manifest to whom it needs to send the Result of the computation.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/developer-guide/index.html b/developer-guide/index.html new file mode 100644 index 0000000..9c8dcf3 --- /dev/null +++ b/developer-guide/index.html @@ -0,0 +1,862 @@ + + + + + + + + + + + + + + + + + + + + + + + + Developer's Guide - Cocos + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Developer Guide#

+

Getting CoCos#

+

CoCos is found on the CoCos repository. You should fork the repository in order to make changes to the repository. After forking the repository, you can clone it as follows:

+
git clone <forked repository> $SOMEPATH/cocos
+cd $SOMEPATH/cocos
+
+

Building#

+

Prerequisites#

+ +

Build All Services#

+

Use the GNU Make tool to build all CoCos services: +make +Build artifacts will be put in the build directory.

+

Building HAL#

+

To build the custom linux image that will host agent, run:

+
git clone git@github.com:buildroot/buildroot.git
+cd buildroot
+make BR2_EXTERNAL=../cocos/hal/linux cocos_defconfig
+make menuconfig #optional for additional configuration
+make
+
+

Testing HAL image#

+
Enable V-Sock#
+

The necessary kernel modules must be loaded on the hypervisor.

+
sudo modprobe vhost_vsock
+ls -l /dev/vhost-vsock
+# crw-rw-rw- 1 root kvm 10, 241 Jan 16 12:05 /dev/vhost-vsock
+ls -l /dev/vsock
+# crw-rw-rw- 1 root root 10, 121 Jan 16 12:05 /dev/vsock
+
+
Launch the VM#
+

To launch the virtual machine containing agent for testing purposes, run:

+
sudo find / -name OVMF_CODE.fd
+# => /usr/share/OVMF/OVMF_CODE.fd
+OVMF_CODE=/usr/share/OVMF/OVMF_CODE.fd
+
+sudo find / -name OVMF_VARS.fd
+# => /usr/share/OVMF/OVMF_VARS.fd
+OVMF_VARS=/usr/share/OVMF/OVMF_VARS.fd
+
+KERNEL="buildroot/output/images/bzImage"
+INITRD="buildroot/output/images/rootfs.cpio.gz"
+
+qemu-system-x86_64 \
+    -enable-kvm \
+    -cpu EPYC-v4 \
+    -machine q35 \
+    -smp 4 \
+    -m 2048M,slots=5,maxmem=10240M \
+    -no-reboot \
+    -drive if=pflash,format=raw,unit=0,file=$OVMF_CODE,readonly=on \
+    -netdev user,id=vmnic,hostfwd=tcp::7020-:7002 \
+    -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= \
+    -device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=3 -vnc :0 \
+    -kernel $KERNEL \
+    -append "earlyprintk=serial console=ttyS0" \
+    -initrd $INITRD \
+    -nographic \
+    -monitor pty \
+    -monitor unix:monitor,server,nowait
+
+

The default password is root.

+

Testing Agent Independently#

+

Agent once started will wait to receive its configuration via v-sock. For testing purposes you can use the script in cocos/test/manual/agent-config. This script sends agent config and also receives logs and events from agent. Once the VM is launched you can send config including computation manifest to agent as follows:

+
cd cocos
+go run ./test/manual/agent-config/main.go
+
+

Testing Manager#

+

Manager is a gRPC client and needs gRPC sever to connect to. We have an example server for testing purposes in test/manager-server. Run the server as follows:

+

go run ./test/manager-server/main.go

+

Run Manager#

+

Create two directories in cocos/cmd/manager, the directories are img and tmp. +Copy rootfs.cpio.gz and bzImage from the buildroot output directory files to cocos/cmd/manager/img.

+

Next run manager client.

+
cd cmd/manager
+MANAGER_GRPC_URL=localhost:7001 MANAGER_LOG_LEVEL=debug MANAGER_QEMU_USE_SUDO=false  MANAGER_QEMU_ENABLE_SEV=false MANAGER_QEMU_OVMF_CODE_FILE=/usr/share/edk2/x64/OVMF_CODE.fd MANAGER_QEMU_OVMF_VARS_FILE=/usr/share/edk2/x64/OVMF_VARS.fd go run main.go
+
+

This will result in manager sending a whoIam request to manager-server. Manager server will then launch a VM with agent running and having received the computation manifest.

+

Runnung Tests#

+

To run all of the tests you can execute: +make test

+

Protobuf#

+

If you've made any changes to .proto files, you should call protoc command prior to compiling individual microservices.

+

To do this by hand, execute: +make protoc

+

Troubleshooting#

+

If you run ps aux | grep qemu-system-x86_64 and it returns give you something like this:

+
sammy      13913  0.0  0.0      0     0 pts/2    Z+   20:17   0:00 [qemu-system-x86] <defunct>
+
+

means that the a QEMU virtual machine that is currently defunct, meaning that it is no longer running. More precisely, the defunct process in the output is also known as a "zombie" process.

+

Kill qemu-system-x86_64 Processes#

+

To kill any leftover qemu-system-x86_64 processes, use +pkill -f qemu-system-x86_64 +The pkill command is used to kill processes by name or by pattern. The -f flag to specify that we want to kill processes that match the pattern qemu-system-x86_64. It sends the SIGKILL signal to all processes that are running qemu-system-x86_64.

+

If this does not work, i.e. if ps aux | grep qemu-system-x86_64 still outputs qemu-system-x86_64 related process(es), you can kill the unwanted process with kill -9 <PID>, which also sends a SIGKILL signal to the process.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/getting-started/index.html b/getting-started/index.html new file mode 100644 index 0000000..163ceea --- /dev/null +++ b/getting-started/index.html @@ -0,0 +1,710 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Getting Started - Cocos + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Getting Started#

+

Prerequisites#

+

Before proceeding install the following requirements. +- Golang (version 1.21.6)

+

Getting CoCos#

+

Get the cocos repository: +git clone https://github.com/ultravioletrs/cocos.git

+

HAL#

+

Get the hardware abstraction layer from the releases on the cocos repository. Two files will be required: +- rootfs.cpio.gz - Initramfs +- bzImage - Kernel

+

Create two directories in cocos/cmd/manager, the directories are img and tmp. +Copy the downloaded files to cocos/cmd/manager/img.

+

Starting Manager Server#

+

Manager is a gRPC client and needs gRPC sever to connect to. We have an example server for testing purposes in test/manager-server. Run the server as follows:

+

go run ./test/manager-server/main.go

+

the output should be simillar to this: +{"time":"2024-03-19T12:27:46.542638146+03:00","level":"INFO","msg":"manager_test_server service gRPC server listening at :7001 without TLS"}

+

Running Manager#

+

Next we need to start manager. But first we'll need to install some prerequisites.

+

Vsock#

+

Virtio-vsock is a host/guest communications device. It allows applications in the guest and host to communicate. In this case, it is used to communicate between manager and agent. To enable it run the following on the host: +sudo modprobe vhost_vsock

+

to confirm that it is enabled run: +ls -l /dev/vsock and ls -l /dev/vhost-vsock +the output should be simillar to this respectively: +crw-rw-rw- 1 root root 10, 121 Mar 18 14:01 /dev/vsock and crw-rw-rw- 1 root kvm 10, 241 Mar 18 14:01 /dev/vhost-vsock

+

OVMF#

+

Find the ovmf code file:

+
sudo find / -name OVMF_CODE.fd
+
+

The output will be simillar to this:

+
/usr/share/edk2/x64/OVMF_CODE.fd
+/usr/share/edk2/ia32/OVMF_CODE.fd
+
+

Find the ovmf vars file:

+
sudo find / -name OVMF_VARS.fd
+
+

the output will be simillar to this

+
/usr/share/edk2/x64/OVMF_VARS.fd
+/usr/share/edk2/ia32/OVMF_VARS.fd
+
+

Run#

+

When manager connects to the server, it sends a whoAmI request after which the server sends a computation manifest. In response manager will sends logs and events from the computation both from manager and agent. To start run:

+
cd cmd/manager
+MANAGER_GRPC_URL=localhost:7001 MANAGER_LOG_LEVEL=debug MANAGER_QEMU_USE_SUDO=false  MANAGER_QEMU_ENABLE_SEV=false MANAGER_QEMU_OVMF_CODE_FILE=/usr/share/edk2/x64/OVMF_CODE.fd MANAGER_QEMU_OVMF_VARS_FILE=/usr/share/edk2/x64/OVMF_VARS.fd go run main.go
+
+

The output on manager will be simillar to this:

+
{"time":"2024-03-19T12:38:53.647541406+03:00","level":"INFO","msg":"/usr/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 2048M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/edk2/x64/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=/usr/share/edk2/x64/OVMF_VARS.fd -netdev user,id=vmnic,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,addr=0x2,romfile= -device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=3 -vnc :0 -kernel img/bzImage -append \"earlyprintk=serial console=ttyS0\" -initrd img/rootfs.cpio.gz -nographic -monitor pty"}
+{"time":"2024-03-19T12:39:07.819774273+03:00","level":"INFO","msg":"Method Run for computation took 14.169748744s to complete"}
+{"time":"2024-03-19T12:39:07.821687259+03:00","level":"INFO","msg":"Agent Log/Event, Computation ID: 1, Message: agent_log:{message:\"Method Run for computation 1 took 51.066µs to complete without errors.\"  computation_id:\"1\"  level:\"INFO\"  timestamp:{seconds:1710841147  nanos:818774262}}"}
+{"time":"2024-03-19T12:39:07.821994067+03:00","level":"INFO","msg":"Agent Log/Event, Computation ID: 1, Message: agent_log:{message:\"Transition: receivingAlgorithms -> receivingAlgorithms\\n\"  computation_id:\"1\"  level:\"DEBUG\"  timestamp:{seconds:1710841147  nanos:819067478}}"}
+{"time":"2024-03-19T12:39:07.822053853+03:00","level":"INFO","msg":"Agent Log/Event, Computation ID: 1, Message: agent_event:{event_type:\"receivingAlgorithms\"  timestamp:{seconds:1710841147  nanos:819118886}  computation_id:\"1\"  originator:\"agent\"  status:\"in-progress\"}"}
+{"time":"2024-03-19T12:39:07.822605252+03:00","level":"INFO","msg":"Agent Log/Event, Computation ID: 1, Message: agent_log:{message:\"agent service gRPC server listening at :7002 without TLS\"  computation_id:\"1\"  level:\"INFO\"  timestamp:{seconds:1710841147  nanos:819759020}}"}
+
+

The output on manager test server will be simillar to this:

+
{"time":"2024-03-19T12:27:46.542638146+03:00","level":"INFO","msg":"manager_test_server service gRPC server listening at :7001 without TLS"}
+{"time":"2024-03-19T12:38:53.64961785+03:00","level":"DEBUG","msg":"received who am on ip address [::1]:48592"}
+received whoamI
+&{}
+received agent event
+&{event_type:"vm-provision" timestamp:{seconds:1710841133 nanos:649982672} computation_id:"1" originator:"manager" status:"starting"}
+received agent event
+&{event_type:"vm-provision" timestamp:{seconds:1710841133 nanos:650082447} computation_id:"1" originator:"manager" status:"in-progress"}
+received agent event
+&{event_type:"vm-provision" timestamp:{seconds:1710841147 nanos:819724344} computation_id:"1" originator:"manager" status:"complete"}
+received runRes
+&{agent_port:"46693" computation_id:"1"}
+received agent log
+&{message:"Method Run for computation 1 took 51.066µs to complete without errors." computation_id:"1" level:"INFO" timestamp:{seconds:1710841147 nanos:818774262}}
+received agent log
+&{message:"Transition: receivingAlgorithms -> receivingAlgorithms\n" computation_id:"1" level:"DEBUG" timestamp:{seconds:1710841147 nanos:819067478}}
+received agent event
+&{event_type:"receivingAlgorithms" timestamp:{seconds:1710841147 nanos:819118886} computation_id:"1" originator:"agent" status:"in-progress"}
+received agent log
+&{message:"agent service gRPC server listening at :7002 without TLS" computation_id:"1" level:"INFO" timestamp:{seconds:1710841147 nanos:819759020}}
+
+

From the logs we see agent has been bound to port 48592 which we can use with agent cli to send the algorithm, datasets and retrieve results. In this case the AGENT_GRPC_URL will be localhost:48592. To test agent proceed to CLI

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/hal/index.html b/hal/index.html new file mode 100644 index 0000000..9fe6254 --- /dev/null +++ b/hal/index.html @@ -0,0 +1,541 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + HAL - Cocos + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Hardware Abstraction Layer (HAL)#

+

HAL is a layer of programming that allows the software to interact with the hardware device at a general level rather than at the detailed hardware level. Cocos uses HAL and AMD SEV-SNP as an abstraction layer for confidential computing.

+

AMD SEV-SNP creates secure virtual machines (SVMs). VMs are usually used to run an operating system (e.g., Ubuntu and its applications). To avoid using a whole OS, HAL uses:

+
    +
  • Linux kernel v6.6 - vmlinuz archive with the standard Linux kernel v6.6 with support for AMD SEV.
  • +
  • File system - the initial RAM file system (initramfs) that is used as the root file system of the VM.
  • +
+

This way, applications can be executed in the SVM, and the whole HAL SVM is entirely in RAM, protected by SEV-SNP. Being a RAM-only SVM means that secrets that are kept in the SVM will be destroyed when the SVM stops working.

+

How is HAL constructed?#

+

HAL is made using the tool Buildroot. Buildroot is used to create efficient, embedded Linux systems, and we use it to create the compressed image of the kernel (vmlinuz) and the initial file system (initramfs).

+

HAL configuration for Buildroot also includes Python runtime and agent software support. You can read more about the Agent software here.

+

How does it work?#

+

HAL is combined with AMD SEV-SNP to provide a fully encrypted VM that can be verified using remote attestation. You can read more about the attestation process here.

+

Cocos uses QEMU and Open Virtual Machine Firmware (OVMF) to boot the confidential VM. During boot with SEV-SNP, the AMD Secure Processor (AMD SP) measures (calculates the hash) of the contents of the VM to insert that hash into the attestation report. This measurement is proof of what is currently running inside the VM. The problem with SEV is that it only measures the Open Virtual Machine Firmware (OVMF). To solve this, we have built OVMF so that OVMF contains hashes of the vmlinuz and initrams. Once the OVMF is loaded, it will load the vmlinuz and initramfs into memory, but it will continue the boot process only if the hashes of the vmlinuz and initramfs match the hashes stored in OVMF. This way, the attestation report will contain the measurement of OVMF, with the hashes, and OVMF will guarantee that the correct kernel and file system are booted. The whole process can be seen in the following diagram. The green color represents the trusted part of the system, while the red is untrusted:

+

hal

+

This process guarantees that the whole VM is secure and can be verified.

+

After the kernel boots, the agent is started and ready for work.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/img/arch.jpg b/img/arch.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0d9ae67c6f71189db0bbc3acb2da82c29a8a9ff5 GIT binary patch literal 49516 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�J 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 F{6D?e$-)2t literal 0 HcmV?d00001 diff --git a/img/atls.png b/img/atls.png new file mode 100644 index 0000000000000000000000000000000000000000..c6e8805d5accdeb1265afd22f5ca70ed8001029c GIT binary patch literal 42272 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 literal 0 HcmV?d00001 diff --git a/img/hal.png b/img/hal.png new file mode 100644 index 0000000000000000000000000000000000000000..e7d70b70b81c7cf27afa7b03690d0e2fdd09bbd3 GIT binary patch literal 36869 zcmeFY2|ShEyEl%=l$pqs%|>LNr^F^1GG!hz&$f9UGGv=FZF2}AQ;}I^sEClvGNdSE zmdsAE|3TiL=b(U|#Vj(;)p@z^-Ixij<2GV}47 zIy-Y&*qU0qnmV{~Ia<1dCh*?D$->sk*3#m*4<8So04EP0Cm)|CFAp=nv>+e&kC%sw zUqD3vxWB2jrQ^wj%1*wvaJVTmpPV2U518tbE-x=LKMefRGV^eB_c;E2!`9Km8?2 z9JdIIo@~b2^_0#DSyY3Dt?%hpP8eqGVQXROb~4-XRPIhraCckhKR22?IXYUJpGfs& zMpIW;C$B$uvvPu;?CzwGGuZf_W=Az>{Dq~cRvlXlcbntBB7!H&L$%9W+FIM3QU>Bb zUZsQSY3Gv$Hygl2ujBDQoBqnjQ*OFCIf40p6WZ~M-~UIMhm0j0#q3i)p3ngb_wOJ3 z2RB^*FpdArbZR$^EzP8rJcaFa>|FG9%)LB}RZi8*(-iJ;!g6LlAvoA5%)-_a?8D97 z=R}c(Ts%+=fLS>?x^uey)CrXO@(MWvy#mI0`X2nUM)i|d)zAd*y=(!?`FNz2fve!r zxTejip`r$UnVUMBnt_@5cx2SHPDuhT{iJ$4!Li7GEr8F}$-~j&r$<4#11}p}cS{Xt zQ($uZvR**ZL7R=c0~|b|UZa+IqPe_6sAu3(WSrnm$0o>cC1P%AZVuYr++CgQEq{As zCL$;RGzqmOl-)X;{^I_LK!7iBw>&i_RIh(sD^3*%n4_hWgQdHx5196JIO-*e%!wrm z0Ppzo+3S~H^9!A{+5E24rvpt-Y{~kMxlz;oGx`SloT%%+zW%?_>c3SbKo>>&H&xPB zK5qIilA(p5rHF;V-^oyf&x~IPC3TdjY=PsDhTB@BoVU9ZN==Se_1`O5-cy17Tax8F zbz}c?BztmP{3cmjM_YGr-dnl-D*{H@(0|TIg?LOwd4<6=C}aN3M6G`Q1MPn?UOri2 zA>i!)n?x+|XXEAL{~O~y75neTduq`Cb0mCn{{JT7Q=j~wJqGM8T^&*Iedr#<}t zbIQYesuaKbhyQWPqp7H%EugNZ@1bF(;O6G$;^PS8{TmFSs;w;dKif0>y!d0x@lq`< z{t{071=G1XdAR;Wl3>W+qMH-!=Wgn14MNGbg=&hH?K^&%Z=_f2$FHMNfaRAaf5_&p!g2f2TQ} zm<1~4u{<@3W6MHW!XLKuyIK5Uf<@Kedg1(I(YwsgA+VOTPO4X0p0(7^Z#@f$Bg)AHvNCv z6a5wCYg@Xavb28<<3NG~mBjh&6gNEyq0NE!KqWH&5?ediT3DcRMSmOg{TT!NB{_pi z)|_OT{-q?#|5kt|c$#N9kw34}z>NO$T* zo{!@Z;;!N2_tle{321G6i;#)pJiWsCHaCr`1amT`xLc?^2IREGyeKqiOd!G!;Y0JxZxV65! zjL5?lN5unz2FbzK?#ztc+6}-|zjIO1vMg;UFG-YyvXdnDEKX2R6YfVJU(xCIO^3q+ zY-h8Vdjn@_4%}%A_Me%wx)g<%0!fTAf2lK^zsqttDgVxOS}*Lb5Hy@1srzIi9`@N2 z$>D`rXE9$mOn=&WdNkP}GbdGz$pD>n4vPNRn{UjhvrV78E~NC@o^i6A)rK0i+@+|X zrM;2creDdhKdP<_}(>tGcG7UWYwv7YI zXzN$r8DTR-Xhhp%v^`n*-nioDaHQ%H@Z{p~ZR!1ZvLIwcNIdU{!o?qzqKgGe*%CB6 zZRmm5?bbFQ4{JVGqp<7G#U-G<@;OA~sBTnvqko0@N6lB&HNP*E?9dlS#rPfzqw^tC z`(78N>{H5ukOk9K2_uZM*uRt%ipUia*!bBAD{8@9tmpbat&nTA3i1GOHj zWymU!K}bwxHV8jymJv42^&Y;iUYu3|W`bwAdNA+y$nY7S$Kr6ziytp;6(QRVc(}2! zu?7}y1%^+Zr=pTi#?vZ@PUGu;y-yS$?>wh&xt|#Lnvxi@X%1b_HEO z`Ysv*5%VT2BEn+qpiGPVyPmerEJDbRqALikue(cpe!r})zd>ug=*Dh;j{Kp~mN3DA zDY1iObtIp47cD!qZfjmqqfI5>!*BRz?8l?*@g3{ofQ2m&VY_t)8vW<)%m~c0sa?1Y z`2I5DJwJT%u9v!G2|3Xc$SI(~n&m>wTk2xVXi|2%=@^^kUiIC$6ddG*uK8S^;?cxI zdIDAzG;86ke*H^Zu`*o(v`ry=ru|% zsi+x_JIGg5QDhj5EJFA1?Yo-1PSeeyXC>JwSI5Dn!898T<9hmt5+2{gq^>Ao^7d>) zUrRV<*amHLTI8+j^=U#^Pfr#-arFul=7kUYetUK6!xwQP4Thci3IsE3-p6XaUAYqy zQfwD*H)!pBvF`Si5ZIsIebUdiu|b)$DHF@afnt1QF4U3RF*5RVw1^7HPeaLX)$4u3 z$g?6n9Pz$MGbmzUABoCNd~bd`q4O@klA^PJrY58K`hHgR=J)e^mpb=1?M?Yfck#a# zo~5Af4+|Vhv{q3SduPw_;pvi;pXy2uvs)@m-lU{eG}y1FtWnJO_WqWn2di-Gdbfx- zHUre17R}thZmZ`$yI0R-)_aZlk#mM2Qqh>uJhePo;xBt?*%LjW_Ib?MT_kn@dFoJDt;Fg6K~fOh|$&WZv}EQ7k5L$iB~g zU*uNSy`dG(okvdk@=zkGwqyc!`Dy8cbY}Z_j%N6pk2wx*RMC`4BQAW;=`czMotvG| zk!L??+@UFO8u$x$>I(_gZZC8XWQWDt}PkSJ%BU7VDUQ z?xJPHO?ksc_v8k4!CZ9>xxUX?A+|lmpOPf5xdIX$d3Ulfr*ZF%^&GgA8UHBueuKz* zkhe+z$vLwVFPRzsRnefD^`-ckMMn3}_^Cr=MaD1CJ78~f^Y8Xg)T4-`72%g7fI zp-arknsim9l|>j?uNVi8Gi9a+ja~XVrNA4lnJH8I;tU|-6U?~5#Lpve7 zQG3s;(YUN_(wR1w1RV!AM(Qq2!1uwmT)oEvt2Yc@Da$-{#zGBXAjZegxtJB;wXpSq z;^4#TP=yF>xQ#3t490{UfBZr|mCtAB3=q`8_fMVFHR!^}WctWPJbmYDtb>UZeTFml z$xGles1e;vLhef${0@E6*DAG}RS074H51?jq2cH%er}2RR91FHjNiiK^#wAH(x|CY zCU9!fJteY>S=&9dsyWEEQkcooXNq$^^K)4yZ0HliakksL$-}$PNk=(x;)$D@7M5 zl`=T0&W?Y^_$d-8g5Yp&$G)7)8L^wi+e!+80cygYK&j2z*xu&BV3(S{Z!U+VCx1Je z!mgJqhT6W3Gy~#@r%a4b(4u@8&dPbvbbSNUc~wIc)-ZfqgIDR1e_&Fl-o<&GWDa#Y z6pd=e?<-$7y}n7*Z_NYDf?d6adlhwjsfqH1mF_<=udT*nO<606bjbdL#I?`g-*W~C zXWw6G(ua@=bW5z_rmm{>HZLy;x4o>q+HJ7dAzZCbAJwhG-U=PBoX{@uOtb z9cejODld=YdK~NJue%TB`L;FdcEUAKl0ZZ6#BC2L-ZC>ibgP3 zGm3gnhjGQ(QP^d&C^TEJU&;B&qM#scOryrld%yTO zbWVA!E%^oe0`9FhugX1^Wp+%#%EL}pzKB~QArb1m&+2%u^g7k!bTrz_H`Fg;LUKqM zezGD+1?9jnXqq??2*qxF{K)f(c*RR3$M0NlITmw1;fq6{aDGAtsHW?XjC>MDV)u-k3Xc2gzgf8N7XS4hCbE(!@qFj0_m5IUyDfZn8@VQVo~*c-gS#UUOhr zmOG#~hO7sQw?Rmr4Jx1t7bHPnv}1i?fS$W@7IXaZX=e2&DV?C805?=h>-lXj~-k%d6W z$w{d`uohx=lhcw~XkCntFUQM}(E<8lwF3eALGV+YU`eu&cqT2}z2XJq>czJ({Q%dZ z$)|T_tu^_*#P=@gIr?rausDbvU0$w#!BO4S5p$Tw+=hK~OS84ebxT{oLP^<9{~329 z{zl=e&rdZuXLZP7P3}MD1FOH=T&(-*Csh4paJRZ$YVC#|;^54|+(gD>oA>iBAf$Rg zdj?|aVMABTh(Pel5dFS|X1vI_gs=IB?{xvWuAA5uMy^d8VM!6xSy>o-0gNiM&vxT7-uNzp+`^`^xXnq#vuqK;jU^ z6fUbQ->UtRTGG-{S-x?CIBSO!IVooXFzGflSZbzsKTBm%~YEJy2JbC^Keb zV244`qnTP)#zxK#HEOthBSct-=*moexD=G{9t^ z8D=rOzD+QqT`8zTviZ$b^_AzH(q|p2c83Rvr4ktjtle*g!j}zdTj9npeSq-6z-2$CYXCM@xE8+u0@H; za;HjR)}mss#!lFjD z=~ey8egvjND;{IV*gHqe&>k3dIGWhKUg#Brw|cWcp|SYNl*^n4daO50$kv8cM@g${ zObnhd&c)+KN-jB_8?zT8;m8KKhM~ku3kSCm_jRBqrmTGXM(7P|sHbv);laK`i9EWr zQ;~a$+~DrisCqL^^>g-5TUW|(aI@D3lHP?rk3h;#rrc*)`EjJIM3S|@gOBUwXsR5GacRysZ;ILDqhcn;Ar(55;+nrOYTwQRty_E4(Cf2?V%NA6>vAlzy6W*XO0 z|8_duVDwSNppJc3Ev$PERz-g2=q+pe_8>a8W{+teo*o5ghrb){_b0Z!SnqhUCa z1hWPGLrMvo{>HNM5j?w=6R9~@@h?MRusgP%>okgIr@t?IsPDy7*&>{JP zmCy5sW)5BInus&I+_V+zz&|EcJ60ejzFYNZ-a2k~omGg0y=J6Y#ew$oO6N5yS=Z7y zxE)hSF?aHgMu7=oWryPO57ULzFJ<8s$re+kx7>r33v5%;EbnRRHQ+*Wv>wv6#aTe{uG(G$A##omw{fWW>NHz|#=1~f zaoekl<^(N-2*idK*E7yht8x!s52KsDSflR-s3~^rN$^~AUbLiSabC!Xz|q@gXl~+w zPFLY&SWsD1Bw7dqhvRwBSQ1Li3mGf1C`CksM8IH(kb^@eArf&uf`l05O4gdut$Q!7 zwq`RTzLj^RaHtBg<<3|%h9=BNsY`=n6iY%=>l#BYO6Tsp8JtkHzPR)ylZ?*Ceg^GP zR}_?4$z^Jk?QM_V-MU?|f&Qrw?}abI`40A>vhmS^bJ#}w6>-Dz?cFia^v{c=51+WN zu0qncdW7#f;oxe0@o0ZLQydd;Yrk)%#vsY|9Gk+Ggnnz|0J$sJo8=KvnSgit$ak+j zYM0Yq7sx%#!U>Ov;_T9(xxC{w zL(xYP+JbZV39UA8l)b9sj75O8eW&L=Wj>NhtVNyL40sltk8{#tZ0q-RLn%x>B+zQnyvJv$&k?iet`y3kwF&`L@do{tkluTl6IElTmngaN!WqWT?_T0 zN(ZyV`NUq;qMe`RUA>@%bb$rbqDzLb)?PgbuYP3hXul@1go1Qto;)oodcMmy zfs^D_W*OL*3!1ME3z{*O4Fn*S8sqXEgUc zm-1TOQhQ?_3m0`gEiD#|!gH%&fVS$b~|0Y@(YM!03sBV%%!IA2}b*B#BV; zG-?+JwqTakd}z9ELADA}Eo^vKP=l23l}nHUyH`=cpx7*R-Q(w)$xR2 z^a|sm1T+u)XW@J10&dMwJOnyODtjA+j=fc-VvsnU&P`?bHj)N=67=qNJ;^sGKM+zq zos{G-jaqr7es!&2+Ia!tM^iVE%705+mV^+E4?=`xYN$Kk!kGra{KE zEg@Dng+^T%{oY=$YK#v-#^cCzrgKA}B{^YYsEvMypqC;Lqw7fAPd2RxI#-t@*6VLK zf+QYMUo!{Dk3IPKFh_MYVSG@7#Ho^lecSq)hO>so`aJRQNaKT)u^3$;LpOM~3Hj<|eny8>g{zX;qesRM?JZ1?L2beH^t$H6Q{Yd+_ z*bev_j=fJvVZ%+DR#Zyjs~QM=PGX~1hoJ~jxtg6Q1^D8~wAT3ACHru0Kqee)Pcf*7 z5M`8aNJwXNJCsVN-;c?Rz7h3B16+K83y8Jc)C-mK_eY^2H%fvQ^&LQ=1Hn0L2kbgP}7Nrh|NoPc2 zr@1Za@(9Mzuj6nb5N|I5%mfe~N-2n6A`thL32SZPIwN&&w$Z?wXr5o>S5*N&_pSu; zwj||@&>Not6Z2L6Vr7dl1Y(^M=5S$5uhwyucLco2!~2c)dD5AkfHvcHH&*H@x>!|d z6i`#=5Fy2tXYjUuKNyfKS6Y4<>nB`;M?+LGyCot^EN8;C2E9h zbVTmepXz%Y=w{-KJV)|m*GTC5ac7toih;0|(B#*m+!;-X!LBAclG2KD$nb7`0v6PQ z|Hr04^nDHrMM!znzK1i9a4jNaDW8IESNyWG2W03WxVSl=n`)5`k{L_icw~dYwpso} zK?-8Z0!fPu9GNc7^)yBW&N#o6FB6AKR~{$c1>Oz6;?bO!W&nm>`prBegPKASYPMZN zcT0m+A_QDei(~pFGcl3~Y#6M4(3<9*whHTwN2m?R7S$kac#Dy5>5sD=RH;EB5~Kb7 zXvtsk*3PSwPTt!jP!ZvgY&LmBu2<4xpa2F9BobM8fOH=_!xg_ zz&(&WY!M-^TqD^ZnI3S&10qxdDtw|{AO`KAYVX1(GTZM@Q1qn-gA;%Po>~VnX-X`* z9zSnJX;D7KrU*S?0l@LUatb9E&a4^52EYYNi%Tr&z?&1ie4K?S_dF-?^)AK8 zJg1dPq+4ZL{exGHvsEM!4z7~THCK+`*RCIp?ql-avzAt0q^boQ0a8nVh5g5zi%3VK zm(TZgZ&!N3Ug>djxdQ{6nDqRsyGv>of8+wB>_7e42I80%yK!{KzW&& zQ`Cq>y3FvMXoOsjG;m4G9z57(HSnpu4qx*f6opSza$4=fuKCsJgd%(Cc&Wje;Y^It zE^k9W$F;;uGA7$~CESHdh^eC2y>GlZ+oPE_5&1IUZOXk;tc>*J2S39%w?D$Shr|3c z-w9CO(i3&cq?Wf&Rqv{?=zCr0}t253~o7|PHd=qLX#_uO+#EkI{Oi$NSd$ zc{7JC&NS>a{qH90W{FEdNx1MetBUdg>ik_lA9ZKGzW$;2aU|k1HJbfRc!~m zWEnUVdJ5E@c2j79#$3%EkwFoE3Uml8$1WBGTsZWlGEflGsl|u$DOU-=Xwq*3jlZBM zf&m!h436VE0yG8EcEVU}-)dr)ihM(7gUT+G#OD-jg`;?tX@!E*$@z@r)3Do-%4^>{ zMr38%>##`(tsszWtr6&JwFu=(8q-i&@k65_Sj0V%P8NG+Sz1|gQbyY8?TZzWBk{IK zI6UD>aaV2I#t*hba)^7l@>Y*;r9!;N`O0zFItC<1^ri?VSc@8JEm$wG{kmHUIv3wC z;hn?=LOzaOR<#Cj(?Y?m)on%=mNc=i-Pvs;YZWopi(OXdNnLZYyIC}tZmJ?=T3S;; zyg_jwKDy1$oQtGtx=QnEnfT0y(^`NnZUf6&soIIr50!LQi8o|{c8xk#`c!sQM?9UM zt>4kWOqjuf!Q37?w_{f3bHK)HYSmTAv5Yp-sBMqJHR3@%)>z z@4NGq`BHm|gC%NL6{pja&cYLpYA-Pm1E_#|>v{wSnX}L>8bOCkxyRUlO}69!zV^=X zc~M58AQT@mibh#G3ZHqY=Aqn{&b`sPxH5W?LWAxA9k+s zIh2`K&mY|Q;5+|gyOt}&Zm;*TSI>M;;_JEE6(0lPxUF;YK-GsIY+A4InKKMKDl1v^ z#3SdiI?ldD|@gx%lM6D`0=$JK`|8P zm~`(oa+_Yx^|%b|vgaAeKSl%xU*iRd)*kiStGi!XGV6>tjjhm@zgMX7!qj-(EQn#0 zR1e7(C4LR9gHd_DkgH4^xCCGM=4|5jga$N%$5l-3c6m3qv^BYnS@i=w@oKnu?|i%^ zG1t^-U%jxQE9S41;M4%EZS+qpYK_f6U@{U}guYG!=^l{H+@b!6FXysbE#o%!$$ zmS0~wKiORNVj#N)gEHO^*|fyjJS5VjZfgU|c~vy23TKx541NfqAyjM5A9|_MY3fg=l#kI8GDH7xM*eYZDFg#(mY1?X|3WlN{vdEN~vn<3=S$f z$Awf2ZRqQ@yUOR`=}+&c2b3P3fx)iGc<&&kEMU1>t6wble|C+6)Y zsP(q*?ptenl_^ibLN}sqw&m@zidd{R-w*8rm$@gdb})9?hJzkTy(LMLC8kl z*i7PRTNhsO3Z~dE64L5e24J&t!_vrP%PGV|jZZ&YZA;4VdN0%Ns+ePM1nfI;% z*Cb~P`}mLi2#K}so83TN)iFNY+fGPJtwD%t`Qc45utWOp#>GERDx!xm8;D)&Yi~6y z5c4eesfvt1=GGvIvnxMo(66(ZU8`hH$c?upv+XprunvP8B!}Kp7`15YxCqZ19Y=_& zRB>~XklG*VD~0%-%VDo!*9cLiR;#IdFG+l!m^3}~O>ZnC8L4q-*zTSx)^6O4}xNAK7>Ne9!v=tG|34>}|~ixuT$j#Y>IXJwN!HrX+Mco3%c4 zGo4e*S*J$b9TQs(KAGmlbuCR&#!V-0s8(W@Q$ipFzG_vF+-mesmPqjFeVkfWWYdv5 z{k{RBRc4UcU!bZ45X>1;)koJ^p!$>-rRj8j1Qy2$!kW97D-z!GP*SoA8$IPguzLr* z(V*vgTZeCagspi=rUuBGkMQNvKHq)hv)v^DPEoGW<-*h zgPnf0C*((Y2@8Pa_gcaiYDr1?K7B`C^tKF$NG?x|s^?fbCti~y!~_{&X?*Hb(+$t+$rIz_xR5yQf?6z5wrgC&Rcf z75|qGgc>wIoPpQ3&H`3-fFu08YfS|wWn8FUClok>gK2YnpeQKNaS&)9WS ze!*{+{9lqW9cOl5aENNBbtA3S?$A3%ud773`LnDA zmGa4m!SQiPZLpeT;?#F1hd`Vp$P$Mi95u6W@A^K$0@*IkOU>A*+5>PY6=u%B{FIsd zRT8D?Bd%3F`Sw_RpFHF{td2TtpEGl&?^_r}fNM*?bP$Y&Bf<_&Klu6GmXG~hwS4;3 zR2M^K>CX;iE1y@3wa$2eRaE3JB|oP?`2ti1&_<$olN(bUb4jgmHoH?sD50v<)W9SP z3Douu-v?A|g^A)uRHekY3BLgsr+zf|g-FwLc~=aKYj^d7B1?%t8Z4pN`S2t!m}x@3 zv{-W)23x!xP zMwQh(7mx|}1}U;;tEPis13c5jHb@bd92x1_9TF1aHAc?*OW+=wNM!oBpkLL-!;g|QAs88M#WA#isM$IL$q`iFIRiMZiQ;(Vftn+8 zgmTu)hYA(e5D5O|iAv>x=^GxdAdn){eTD`4iJR0JN)bFc0a~a^4 zs%Ub90vO-;P-75+UI(Q{Iesmf%EEJ8`n48iu;y^pHG|rE{j3uD7Yxvi2YA`2{i0%m z?V`>+vc2;6{gupq^}r}s9M;q3WG<)3=NbY!I2s~tWSw{yNKEX?D>V5)Vf zu=}$-s+=UolX*)rp|oNS7U7OEVeChr?s5R+xszyge@LTdGdT|5k9`;|qunCOV*EZgo6%fCQPq(|i$~HQ# ztIPf7^)ha`X{~=){-YXX1h1LMPji=I&<2Zu@pkwLwpi>2&9r7AWW^=x<3=sU3Qa*y z$rKhE3(Q=E3S@|r|u|cw!k0DoZarJCQ zgOtxBs0yUysaQ1UE`h9K2q?#TutvMKT2O*;?0ZTHf%N=1kN)M+SlYrg6%58&?u?Hj z$_})!_dHk<=+$b3kQI}BtpT6+5ZA~AdCob^^NzsUrKFhAu_;OOsj?efCux$Y%u5`( zVT|0{?gR!esQlp8*g%o>qJ9hy+rR198*wG z4$kL}lt-_%g08eLvP^S+5MtY6gjTMPI$C#{CRPoVlUzZ_b|i!uu;)V5pP|wgni$^0 zVJz`iyNzC0iRVN<)fK6rgv3Yh`$lp4aO}Z#!oiBQM0ziPrJO+(h|x*t8KxyU+_zIb zF9OyKxkYH=W{qF{;K(K55<>QVI2s*Ta|A08wJSvJ`daxR#oK4=#e~OfYBg8M$W z_7WimPB-e#ZA9E*utWB>8h4SAafGar^ZL#~0xws%u_a?kTK%Ed+IOC9Xs%>=H zh{Y|_`;@>YF{aTCOl!kkR9Mf`fwDg=C@ls`n<{|CkuX7pCCz9ISZn!t=^gUUEUC-; z_snvYvy4UrKe7TG{32tCQUM%PE&H+wlF}L6QeHPPt|&A$kAuN>BKr4|mP@WQ-7Nw4 z5?l0;4Iz9XBv__3v1SQEy708{sJ^vR*X?-P1Vvg zzX3AF71fA`8~i?7nLgvnI9ErS7#75|r%!qUIMrz2@)-@QEvAB(-XiTE+^`*SK>5nv zlnRj6{Ah#=lOM6S=;a2h%mY@W#>m25aldD#c__WBXMD5gL#m_KU*V10|X!nizx}&_}NC0<6Zm zSOzYHvCEN=Vt9~@-LB1EiUfBUSFWA84K8ST_|UP*Nd-lWWJd0c1Xzfhw(ML`kjI%Y zf@ha&l~aN{i!D;zjWd8VbC|U9@`E$F1Xg~pg_4xV(@aOq1R#(HomDX=2F*gkPda4e zTRbp(B>~>>hkQnZO}fRt7cTJb(2oe5lv#?t1bz20aEkl>==sX!=*K1?F;3xA4O|29 z1Wtc(EXV9;>5wzR zs!Ozfo0}w5%zEW}Jq#p3ayPA62d0LfCdqVKIw;b;?RwBBp3&QSeeKSt@A+2WJO}G` zU&>Z=@W`^lR8w4a|56CQ zqmG-{Hcz+l&4?!RSo8v>y%t{AX=)4L10yOG9p-XQb{F&j(6nvVf#bS!T@7C=_;GI!e(AashH-$J zGG_C$vq$}_;u%RC!9HSUOWg(Thkb{=QYMXL1RH*p6QbC1R;sPsP$Q}?P`qUGdD|fj9b&^ z;+grMCpGPPE*Z$gR#?X(y^6eQ+3ZO)c66lp#;z#*Dh{j}&!#9h{S|kNN*^SvR@c>E zD(S@wwkwgXaz2*JAytW&6*55q+d!`QZJEV(eeATe7ivqh*7(;4-@H3RhbmT)u&fL& z6rL6pUFp(UbRXqiLw1|<>SYzj&Ugbe3eb#*Pl3FIbrh*gyg-MQksxn;5W)P0;+C_Ae&LVwQP2?RV>r1eSV zC-Zs-KFgaRo(n#FI?_@6wz{>NWj5(uGgxlkl2)b!UD36QoIwu{bl=@?Y+sdhg7-9U zDa_E3=kxo;--zGPH@=(IkYY+F$>b8^6&PLoGJ9_?sSumHj9r7R@ezl4AeMrsuk1T{ z*_x5HCo7@O15BQGNIsRzV2I)33QNA{Fy*jElzm3rk1hpk~b#r6V(a~}BFz3H5CMp_l*1dAoK$#21tW@wcydqd~gg1CwgT~(5&fFxa zG3lJFUiT$;{bVIkIX=9^hS-6~dIOuLzVQZT_ksjHs)|PGqPTJmn#n-jOgi_u8EWRd z-ntze#n){|l`Bei_g;z@2rYU0Q`OirLeG0#Q3*y5CMPC-;D7dP*zSjob+p5@m4Vrf z$nkaF zT_UyGy@&R~Zx&%W0`KRsh^!`NUq}>95KYQ{i<|>xRU3Qn?biaAdzza<=_S1%9?ar+ zx4p^6!kaCe3RhKgcILstu2{8Bj|(Xd0QI1YuP3PlUvghfbuDDeD+%-_+gS)nR9Q+l z)Pwsh9IB*mmccE2jiEB?k_K+f_`In6+1@+v53VkrNwDU}uZW;&QB4MRy|UmgVPTMJ zZ+0)6m^7C69XudKQiHyCK!$62VeK%iv$ZwUaL1|eqjyK4Kljz11Wx?j{e6u}3;!vr zIv=GJM!jb%8U>2d;or*gSB<&ec&NP{Q-#Q@cE!DH<)K|7sy*@Q^uYG<5sS&z7nWLSxQZ!pf`gTjrE%IJ``&@h!xK+6B zM(D|`*D&g!4DqG=j1TbDpc)$shM2O$XE91L@8p-*Cdp{W_t%eclX|w;Zfn_bIE^*5 z5@qSPEmA#MJyYzep2iWA#1>_{KgKpdMG{rwC!gAq$aPf|mgm{NwSANdO6>yp8@jm^ z=d-e&T)84mwq31B_+~Kdy{SyA4Y-4*a`Ohax6xzYH|a3aljfEtr=j?P?^8i(ylD)= zH=1w?a=U-2LAi>?n)m*8;R7&IRG<>Qs+9K|=GjpsP&k^%}ey zl|-m1Uvd@$Q~(`^6(F!M<_Gym@6Dmq+DyH@^1vVSx{XiPBT%&`-Ul-mRW;wOEA&}> zE7tS{AQY3~J_u!~Qi4)o&D)#iAG};PE57P8>*01Ks!yjZ-QIJj2&FajDBS{;8Er&0ATWzolDZ68 zeYMR(S64T0GvTYDcp){+#TS$)NtXa#2neW#P5!{Q;#$ca0{K7vJ4GPQ1PD|gH*(pjMjMMBT|?(@r8nm!DWk+&f)?US4^E=yP$fOn7;YJVkx!6+m(&jJj~gU*R)Ss#wG zSqaq|-W$qDfBovxx%VF6v#Mr6vs-QBqXU!|ZgSXvZLu>1)gC$Fb$}UiEDu7FA};2s zM>TEMX9?jvZVB;vRK+XAq}12!2eXX}l@r9Kg43}KzG_a9!e9hf20?NGpk+X5Xh7+S zGa=n8O^zi+oI^+9-Z| zHv8)S`;4v7K0pdYsnl|vem{go!IfXE5XaUnJbO@$a*~6KR*@=2>iYR_MLi96!t?X% zdSUAhxOWwSc+*GSSh3ijFltx*E{Q!=D+|=SHHRsJJ*@@>QA1o7JFbZZn77>t*etAx z!M=3P0}l`i@APwPb9a>P)}cwAOKPDW1~nmSG9Z!;-jM<&dAheP!UBUj$KH*5%u2=( zaYVZlf=>-)qlOjFb;Z}p_cZIV>vFJwOb8B+AxJe)-3h9JO}@sh;9k@<4 zDLbXd3Sv3Dxw)86--a&rGMXnKIymgmVa<$&B2=iv7D>6Be1re`eb4*10v?0!0rjRx z@MJPU21Dh`n$fxg3DGvW-{N^&`}hQqn_*)>B@RrsF-u5DX;iz{{Vr@&-uL>UXT5xg zIc19tD4kof$$oO%yU%hZAxrRPYwd+UGJUHtLHV%B_V*4w-(Ec9t2F*pOg2S>&y-1o zKy>#}S5=HH^pD!V??y7#`@z#el_&u-?HLe>T*TF7gnpB(UkKcIOBWy!A~R+3i1&VBOZ>e z@3U&!AY`W3`$CZAE?hgyQ2QF|h9&Uhd z%fhaSf1ypzkSIZR2crAWo)6D#bX28qf782CT$}ZU z0JDUNXFqjRz`Xg!!eAAX$4*X&hl(0LrT~lc#-8Uy8@J=~in<@{cFe8UnR4K~5WujF zq4DWPJdQG$cTz4jDeUgcv4TPx87@|{e4%m%0~%8T?XPp%<0HvzwR>M z^TZpTm@D1)$O|*2r~1HUTErAOA6#a?nQOXE(ytCyeAl8Fu_Q~|_F6q772fhL@+CXC zBI}9~+nNh1LF5sh6&G1a6y9oRIGld>+KYTHlvVqKw3OK#1_F`UVzUwEI1V8nthdPHG<;_8AZGWt(oVDRs&u6N&p~5V*jzzd+|pMuBcv zzGMTBUfUHbjdHs?4{2)hK)K7TD-P0>;tTY3q^h`xF1dTEBzlqF)Nt`DrS@?u*jX>8}nTD^fjgR#4L!QUFdMWF(#9S|M7wtd4CZ8n|L$^hK z>n;)IT}w8VZm#Ym5d|~fy&blE#l*WtFMXARgM;1Ih9Y;I?}}iHL%$zvGSzK;PnuwQ zSx+>M*&wzfH0KcLR5mKST>f~Dv_L3Y{A`18jnY^0&x1p)qNcMCaTA$uq;l9V0NFk- z+-$#rODc7STDWp+VEv3AVQ<{T)&umsy+j>1ZuWaQ#F@_n(}zlRuQTn(8Ia&w-<+s0>x(#?4KlbA$Z*k)bNrrB!gb!mRz&JbcU zy%!sL=hCzI#~RHn4R@apUT1R~cXRPn&XQ11haS|qDlVnmH@ttVy|p98F!NJ;N5?3G zb(rG^GW05Bd7)$u_ZtS(XNBm}4HA6+tG%y&i}LIG1whWo!{P(fy+I5ypYeyNc z$}I0|r;X64s8MqOki_lFupuGbmShNdVk_vk5#sc9{RrOu%PD2xKM;czU%`_a9&!q@wwWH{rcfz{iA91APcs$bg6y z8pQh*D$O+(%@4Ed9`J^c00x1z`}>Me%>fQW#2KUu+sCU0__Jyi+nVYFD&G1goazz} zgA0YAGh8sk#oSH?s7b*B&E7+ILt%!k2}Iz+R8{~D9nA15T#PTMKkJYg-~X|!4k2Km z1J)cK8vM5?XY}9Q6$?0yEqaM`Gx!Q~05iVi2aY)ZP3u1vPz5;jGME*e@1cJMhV{15>K7AX^+#&!m7U5-)Alu5FfkONxy zyniv(^t~Ed3!2Hf#J7F+z4(BigR)#ef4YAxZ6|Rv-tT%cu9#B`03uoDxH_G)b50wM zmX8GB{uP=64wLLd|SPmA+Q&(Y8W02wWoWpoGn3TI(vg2A@mc8nY1*H(X& zP6FVVZaN&;py-m~?fcz{RqA&SwQbHvLME6IpKoTulN)?{Bf`O6b}a=4&D zV|T2#JjlY1iQDWkeu*hGHY- zb0`KxMR!M5tpp0#(%_KEM+p_rzQ@MPS3JBcSLIecTu~$dM`p+Os0oI!Z_e}ASXtP9 zu7%P-67Fs0*7r;yCXQ7vnasJNH2N$RUF}KoW76qfUSfbn*lg@CuZS$%!x+X66mvhO zsFBXWsh=4f*N@uv)s&L@qnE>IM34is2q{`wpade!4i736^l6idf?w`EI9Mr_kctmB zVr!Z((l=oq#WPO%V#ELtO5`JBA|3<^t+9w;uCaf-tWKoZ^=rKBCT<{5uCwX`lhLI_ zN6Qxh3O!#hF(80xgLt_N6`>l#%p?S}PXxnw+Y!exy(t(iBdCD5-RJlAHMRKFp@;bwMxN9Drb!eAx46d%Ht?40HT}i z2L@s654<-(;xC{p?aZ2iBXn3N=gMO^eow&_`?m3$nJii~;T65Ocmxz!0FEm#9m$+Z z&1H1s3u}tTsc~nOs35H1Q5N?FP#yV%lMreg)>WPaHTrKRy5ah|T9BQDTt0wja-yPB zLHVU@9yIGz?Q8dwjFgPLvk^3#QO9DJ0T>v#z$>|3Uo4yu%UcS&0}7?HE8exRO@=u} zn@R)Os!Mh3(@qvH6T6knrq2gWbkpgBxs03r5%(sGA(Nm<>BS+g82K^bp6D*Lng$DM zs;m-=&SS3M5sp9xW=&3CrW^sZa?*&|7ls)cio~aUb)rh-*GC$tWI_Gb=pb8eOUkjc z$wv7ar76IEV$)N$oFxKONpb#2`~ZmM|6lU{2g*nB3vW<>CY}QkQ65Cknn`GXgR8T9 zER~3l%r_D5kG}UXlpAPIod4Wy=QmM-?qe>6v@KPx=gXtJC=xvcb&#Ws0`i`dx$%?e%J1#*{r&?;sK*~d;^H_4f;X8I%|ULA=IP3erT6LnXcz;QJtj0 zt-WkwbO)I3r0ks{>YR=Snh^4?Wxd&$?T-a2mxBdfa$R)6{8T`%x zFs$0P%n5YVK8C5Uwe{l#Cf0q2UaeA*w|!)jQFXM^pM2GZF;Sy+uwqcdQgxaS|1^b% z7gi=svvLyO4fA=XWW4(EKvcB5j(lhK>rCN#OaI7ISp0CMk})@Vl8-qm7-mC{F@Cn~ zd9^Sz=>`z&u4XbIF6Yvre+=BGd|Hc7Of8cM8-CD_*9S{tym*oF-dpQ$FKvwE&1_%x zoQwPSTg>(Bh7XOyWT~xw0L~Ds+W@!YJj!S)=a1!MmXTWv6fD3s9@x6u@p;P4zS+qv zOf}48NeiMGx&eDWDf|4`+R+%rCYv17)LQTp(#9`*s0q-#=|RaFO+9C;U$4j`63TAy zy@4t!7h{Toy?c?=o44VOjsb|DNG5Gmm{!;Vw4KH_$^CQBWpj#YTrX(wfalF~VDu>) zm8R{>(?UCAKF8hwP6ART!oU-<-}JgPFc?G2|r-B#JnYO7iEr&ez{V}T980GqMlyQAmiC-<<#YS(O56^(n= zHh=R0sM5c*-6-D;#}sRIjcGK=rP76DvIFvejAs4uBA-==m6{|~BOhJvU!_oDFy}6t z)5R)H1WT)rOQRWeGF)LOdi)m#ZU0%OWdD5We#6FcW$tA=ttzZElr$D!_)RMD2>>g znAEp_>!t_`Ghuk1?T*0vV|7c)%}90+t9(fPDFK4KTryUVDpFp*P>la2mi^*iP$c}H zL2X(>Lb^7*_i$LMF-SvEEs;*}vq4oN@T6*k$X^%^8hR);Su*d9YYgwv{+Xs>3Bjxg zaHwv|cZot4++Yg>GCh#-J=-3k(@wWFL0FxAe@j%i73AW`ophrL99H8*1)d7hI5#nz|)gyr% zlqG*Vl=77&qC)f=umVK><6s*P=YQbGUZY0GhUIWo-3O2me^0bPk78hKGYPQr^M**j z{|cgedHn`7spyUAI|(^U4L=+pJ@E6tuu2oC3;@fwz(Q6+04U49k#+wX*#Z*?U%0a zyZ+gd^|xEkdDs~|tT^v3FFiB+o!sqc&V!WQiDgI7-EWuQU5Y_~KTl>;i6i~SDVk4< zi|q{Zx{8Hm==kubNX&6yqT^kJlFe0X__Lhz*Di|~_aEGU*NbsKdasp)CtmlmHAm=$ zLRmqvfMl4`&MA41z&p`~YD*?s`DC8tv@|-o%zW86rK728vxE5Ih?;}XTU_?nGcJiU zx!exd*X*u`*Sy9By6iLMORZ+9O}~(aW6S-lz?Gk2>bB+ZOnvIc{D`Q*@d}q#CLS5I z+Ak~QKK$iV94qB}r`eL(Qktm(BUl|~2 zSgA|}LlM_M-pDPtZ&!&Xv2Om#mbEvVRO*WpaI32su(*9D6f2nj&Ub}hSv~K`?z4|V z$_@4^G2Ju!B{~d-QyglYW3e%|zs=J-)~?i;zgpC&?g{qo#fCjEY%pIh(anyiT;IP7 z2)@3%K{xJ2dXuUa$_Pw*W?#dxp9g<6{qe<|6*%?xX^_sHT-n@(uhc~qs=5EHjlW&X z6C`Zsb@f_FarpcHW!%ifB5ChpTu$mC_zZa~U(f7u4r} z+Lt2Bdn5TH^<8~zaW9QD_)j1FNu|+%aP6K@`XrOu&ls)Rk3u-n$N9>mr@nW@*jRUb z5>dp=Ie|hanc*YZs@FZ8>Cz{E7&oJ+%_5<;xh2I~3@y|Tv8qKg`w{P|+(+qLFD^L; zDS3U~|0;Z5@&kYk88B4@?}s)zF<5_pBa?y<&D0sqQ8`+!=-W#bJj;eFrexA?ahKtr z$E(TT^2)p-AS06tZFGEb@qMmY-h4Iu)~+?K>eCk2`$lu(!RN2|s{jPvtCIEbzD}rt zbPE4{RTfnx0)L0s_9`p}^5$b8r}(=h?x6jP5*K#T>E&)IL!zY55NhQh5ca0qY9#H) z{$$O?YYAFti`k0A36rWy*kjP6tUG6S1-+V(hid~8ZbSpY@0{}~%oxchl%$HLYEoKA zIO2m=dIz})RT(@ARE{ZeYF*%^IoG_lWj4uT*t0XDhLAgAx0)NJ3qh#g##*x*hvg>a z%GDulipE78_0-B80T8tj!4EG4-n)-VhW$Gz1)pzjdHb4)mZnn9FzdA1N!EYpojttm z42~8WBP52U>$95<$Ak(-(-{NNH`@&6v2Eqmr4K{6@$ieY)16<3xq`=(^Mfk~$12kN zmw$jrk(Zb7VUcpc``^~WT6kpX+M1O=gVJ7jP(fFgZnphd2T9p9>Vt8$#D$r)8^c)U z>J$iFPanla#B-%ndQ2B-)-4Yf5rvRSr;QgAZuU|LdL%M>OsWw)KVb@J)rt!l1sqx% zhh2|lbSjZNr{lJaNOsfceevX;&fR4LiI2S#uNK4DuO=!#2*xmI(<@QNhTs4<)sJ;H zH?IdxOsK&Fw2Tmf$@An2BkYsZ^U6pacGL7@GHq|z2W@TbqEGE=qD%E@luxZjR0zJZ zQG7pD_wx#Qu0L7dxt<|Pt$b-uX|%17ETp*lzB*%A$Uc{nSL^{0HJu>O0RxPE`y9wF zrtH#o2PzpdoK%nIh|3s^XM9(wHGGk{EFga2%j&cNx0;h1ueG@R&}aB9k<;DVnebAw zPYD7cj(en9FdR<_PiJA)qW>*9coFK~U&`Th{`S*sy7yt_9N~*$gBH8iW)G(7^L%bv z2gM>p9HX9xJk~|YoHoVwoP!u6)i#2)UskJyyk36%vrr|g6(H3}~ zbnR{sVyetETD>0^cQ9DJ5szBr!g7KVUH`NZ!zW%*_}&y zXs0F&7+}I!-Pr~~@m!1V+?$yV&-Y<5LX@#HCd2;cU&-p7-$6q#o5#nI@`J-*Ry ziQqRR0gzD>`h-NBt?@5xkKJt6320*Sdm?5VC77TqaTLaV!`$*h8G4teKwQ!#1+n)V zh?>8d=n-9NuijFr(zIjyAt~uk4gcEJSJhqWi#6QNX`X-cQ@`&Lr(T&stL`N)AD^V` zaAb&hvGp_)94$`%S?;;Tu?P36DDx=VDAuXEr`kbqX%G9TWM3j?{XK3RY|ZIm|GT$A z@d@nqpzP&nt40yAXbT@Qp*llJ*R?aBFGJ@s;G@pP{X?P5omy@2uw;Sn3DGg`-gR=c zLgoaFc>_-eMGeGjOMW@F2}{iM_)GTb+%Bh8T6w%~+QwrXZ*VB`_d|pY+pUcp-MbTS zpb+VJ`)=rVrGHmi?6pH?;%c8nLy5@chd?BfPp!TOM_uy>BGF+o_TC}Sa=DA+Prw;* zT2Bz|ayty#Rq+9KD9!%qZFYt28LSg<(``B>#7+yqDfDJ=;6ICHxvk!6rhXxWocYHQ z2M1PixEvT5!+Lctrk(caTh$GXn*wcOHX9_i#)fO)ciEM&pvuFllo0P$CkyqQs|OAn z=`)Lp@vUCFLY{KD>ZR10ic|&?yK~QN9P^BCE{}cg2O4Gi@bugL*^7~B1qv_mJkcLs z997(8DP<%vRVm8Ao7OO;}BPWBWnlQ?hzAJKVF4wu@&uf7Whb9%AFv*5#( z%yIn*8&`+(57Bm86)eIm=>jd6k(USL1<{%ENy;_hf)C@GU*QD$!eJROPV-S~vF7~G zC!hKb*yC7D75Zav6h_$G&q#vvALrMa&AMJ%A-HvBn<5048aI0SWOVU{@8TGs<}YWo zb@IvPY1NsP6BCb8TqZWZ#uI7vNr1}K;3aq7vN#=+8omypj>u$RmBGNGuHjbUV zup9={BVz12tZW6ds9qop{LA)c}0M7V`hD4)J|_&E4WFHgb$VW0D*;qn`a zM_+VaMAv%9v2i_cG*jGi+RK@Q7aO5-1x3=z7ubJK=5(!rr%}Tsq`a&G>ix@C-iSp}7v3=&3d@`~vO@k!r0?Da_=LpVBtOgRG>$JF!%5sn^H zK)^mVwkFLh;{!0!tmnWkp7DU;CmJpe@-rZBF{Zp$9Woqs*Av62vhQ1&!~@Sb>=yO& zyTD*2Hq-Qbs`~L%46mVUi&oqwK6qxZm%2|U0559$oTnpS-)WAQ%I=E5DHsU$4#0)8 z6-R!IxT_zZu?jJnbFNtF?MDA`*p?&aE>hop_T2=UWetE?H?M|V?8L6DTIzz32*xC8 zoUs+WtNQ9f2Dh~V8Jz?J5^igX*@+5Xm6r+rep&0r4I)7=f#|Zp3Wm`36$=r7hOLR% z^xFUk3~$-?L^i5O7w;|IkFuU?$)0N(eKQpe9yRFaZ$hj1P;!RzF}p|SFv}lD%qh>F zl0BB|u2PS{pq!zcgjnC-uYI!-w~u;G3=YdCF4bkk;rlvW4RH`}Q!`xTNM(&r7|ji@ zGLMvw+I(3*krXUPEM-Df-+hJCQqS*sn#?laAZ_kUy14Ei>^vZ!@gv|_0feeKS8SE7G&FMrwBw+t)Ki@-85>&`M_- zvW>W{j?~ySh4giwvN!`M&Luq-sBIj~Zi9`LIe*JOrjXIey+S~>hCi`3qw|f_d9!D> zMF3|Uu)p#W1GNIwa_}}3cM>^OJ)f#c^+@EA8e_HFEFjuNx(glTUbf*zVRIKup%k@(t?{{>|N5@AtpEO+N%9Co)ZDCAL=&S}v+ z@9Z9WvE$UxO~R_!wKvj$hK9R>`bI#@QLF<9ZaE27keY!X#=DygfyR^N@)6F2-jF5f zF@4x%nMiN!N?)XEuV-)cdkqLg3+{Gs+FvG-g9jyK&p%UK^b@ZgHst9)SX7hEXBuU2 zaJT`-NFv-o}7n$?rKBtYcCvdkJ#&AYFSMnAPDBAr95TP4J!vq3Le-J#C2L? zUkuSR%n#lS{Ln)RMl)(4m4C0t%wnzal>o^Nh#wI^szMK0t(>`gZ?Np3`Tc?QDVKAp zRb1!Mq6EOP)BC`vqoX1{ zA%u6<7VVCpc@NcP&^V_CBeX-mUagpSIx51|^8~Q{E6$rn`_CK6O*8dECms}2R&*v1 zrC{lsqt&zh@c*jT+nTrs$i9 z?W{YzenfD;w?8KQ70qytwa{Gtkq_5EdY~&)C75 zF0bXrNCW+W(9i(Vs1wR=Djm^+K;!Kufojq`Dep=Ailvx}l=6}J(Amv263Lt)NT~Hoi0HX) zlw-(}iw$uC4XE7;dyd>-t(K@dJ`tD0>lX{XT@&)Ot$lK8HK_!7W!fo2+KD$R-Hrz* z?Z6o{dY&c6BvqhM^QiCIW;W<)v=vZPXh0dKBH$LjGwWs({hOrwfLKbDw9?N{$)>6} z@LrynznuSoaBg~sS-pk`ZPv3O`dGB(m&N{HY92biFH0Go>dXE_0@cPi=JI+|kBR^G z8_ur?nZhq)?=46`iI4sLgk4kPS`v)yCeLQ=hANhv?!J-C9c`~wvQEyY9wi$ddrOZz zy~C-d(>rQE+N~YxA;ESL$QFvBkrs^9Gta7+IDXD*Tz-7a^I zm|n_R4@~XG)wCX)LdB$7+TU7G+wi!s_n1lwx;9HCW%e3AyD;f8${!wTe}(9BkO>|=eyV;BgZ`HdV0UBcv^q=#+I8v zSG1BilBJOd&mOLJh*MmH@|tmHXR(jpb{+Q6{iZd(d>L(f-n1L-?6Eth(Rb}6-mOUx3ZupW5zug-kxd9_co*0jN$;Y z<0q3$)cwjHZ^9hoR80y^23**4y06v2D=lVBQayyultqX0bS6;flO8+iqe8z-cmbhi zf0}dqY&8U3F_FbMH`Gs+*GZ(tO0dBq!FBJqL%}z-%Mc^2LXNFIh&f)Iyq!`^rNzBi zBy(t#KxHNQ1y#%{*CZW7<4dCpVNy$4Iji@_S$4|bKIE1r(nczOSZ&P>rQA#9;??tC z7P+~q<=A^OBqi1AZ$Tb=CaRkTGcEGmb;oSWyCj=U6}UQfnzxMO$-Lr0I%w`bNE|O>{wa)wu-6@>sVV5j#1G zlFpa(_B)uwMpwP2lKzDC7|gatTFqSg&f}Tv_YD4~SyHj1Bi8tla9pr$R<(s<%O;hKn2(>_Y(GTBE=TS&+`IM!neEHuc4o`>=c_5ys5Ss*jRTx>OdibggJwQRwmZaem&DCYHe9Ai=lLON zll5Rksbp-Vk*2I8ld~zL<1%;Yti_B~O6o>>)oxb!6Sb6-z(>&SaH;1Gmz;@Hzpc!# z-YmP{+_r#p@XYJO)h#9#lGV-<{RDZx8*NUV{7H_KSIC~Kr>5+yFg{nS_BH&x`rhg6 zCzS*JxFKV_OQWID7g1MID5#g zevDab{1FqIQtANozeS8-1j~ zCzgGlsQm~vDws|fDfNg`M07L(AWHZPjTah5EG7sX`{8RJz@2|H4`>JjXor0RLkHS{ z$5rVuIwt;0T4Cf%+R4x4CjZ%xjYgj+mP&st>Jy4V3;=@|q)nhjGGJ)Yp%NL;8KLDx zMZm3-?hUiVT>9kk>VGm*BbMtwCh8seqAKmYx-BJwjJv!xsy4rF$yur|!n%=Q&( zRH=A05$adJP=Wx60%VJZ0nz|dNon|mGRh)<+SC1&D$uYDDvT_{ltsS80iG>sPE35^ zwrDhw_GqJShxmy9XxJa(r>WuNr>R%~0p`vD7?cA|h$v%}Mwa!-eg-;ISpj-6WAFW- zqKW`fc+v?_@K0uHPW{J3P}%2dwAf%Z7X}oO9n8W=L=wwS;aDz=&*fDay`46wQS||# zb-X16_?r;%Kjh6-07J=)Dg(O*)vzrRpdAboX@>z%(Tm^sfC4H53aA`OKCTaxWBWfF zvV%?ZofMkaZA2zR3J27(QA+3KRnj&`8;pnN=Bk-$Mc&0uqklp%p=~?fecyPrvccp_ zksw|tO0zMqaX9?G54Ft0ZqL_#Z&lueFZDTNYD^&{nGFVNMzHsE^wXGRm;CLGf1~`I-@fzc?gTv5VZfq+3`(_r&TwKE&z!0u^9h_B9I+i4l zf~*o|ub9T4=e@xO#DIoQ?j1gNS*cuUxz$ea)V$B(&&#niKs0H}0qV^fD)tFc_OOG!U8-^0+xxY9 zmq}aof-f4(1X$O?&1Eu{Bqt|V37N+0{6_!7XmLPy@DcbEtp+YS?_Es})QMT#(c?P+ zONJ%%4~WM_SD6BzSE?(Ll?lo=&42;q?@vBOrh-o3=lqlT^&byInc@TMG@LL*+B2Ju z<+9E;R8KCe~vUlT>Uv}pcN(OHP*40@Hh)|>7PRqy= zad2|D*Uodl;apu=HOcaCpk2^(c?d{uVFYZJhr`!xJ|}QurKqp~NJl5j0 z{n3k2U^h8#u_R-sqY*2Y1TsEdH(0 mU@?5++(fDQt!@a@zEExh!OMA9e=#)RCoQ2MULyLz=YIjr_Nr|F literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 0000000..f3d32c0 --- /dev/null +++ b/index.html @@ -0,0 +1,555 @@ + + + + + + + + + + + + + + + + + + + + + + + + Cocos + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

What is CocosAI#

+

CocosAI (Confidential Computing System for AI) is a SW system for enabling confidential and privacy-preserving AI/ML, i.e. execution of model training and algorithm inference on confidential data sets. Privacy-preservation is considered a “holy grail” of AI. It opens many possibilities, among which is a collaborative, trustworthy AI.

+

CocosAI leverages Confidential Computing, a novel paradigm based on specialized HW CPU extensions for producting secure encrypted enclaves in memory (Trusted Execution Enviroments, or TEEs), thus isloalting confidential data and programs from the rest of the SW running on the hos

+

The final product enables data scientists to train AI and ML models on confidential data that is never revealed, and can be used for Secure Multi-Party Computation (SMPC). AI/ML on combined data sets that come from different sources will unlock huge value.

+

Collaborative AI drawio

+

Features#

+

CoCoS.ai is enabling the following features:

+
    +
  • TEE enablement, deployment and monitoring
  • +
  • In-enclave agent, netowrking controller and other system software
  • +
  • Encrypted asynchronous data transfer and result delivery
  • +
  • API for programmable platform manipulation
  • +
  • HW and SW supported attestation with verification tools
  • +
  • CLI for system interaction
  • +
+

License#

+

CocosAI is published under liberal Apache-2.0 open-source license.

+

GitHub#

+

CcosAI can be downlaoded from its GitHub repository

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/manager/index.html b/manager/index.html new file mode 100644 index 0000000..a64da5e --- /dev/null +++ b/manager/index.html @@ -0,0 +1,899 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Manager - Cocos + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

Manager#

+

Manager runs on the TEE-capable host (AMD SEV-SNP, Intel SGX or Intel TDX) and has 2 main roles:

+
    +
  1. To deploy the well-prepared TEE upon the start command and upload the necessary configuration into it (command line arguments, TLS certificates, etc...)
  2. +
  3. To monitor deployed TEE and provide remot logs
  4. +
+

Manager expsoses and API for control, based on gRPC, and is controlled by Computation Management service. Manager acts as the client of Computation Management service and connects to it upon the start via TLS-encoded gRPC connection.

+

Computation Management service is used to to cnfigure computation metadata. Once a computation is created by a user and the invited users have uploaded their public certificates (used later for identification and data exchange in the enclave), a run request is sent. The Manager is responsible for creating the TEE in which computation will be ran and managing the computation lifecycle.

+

Communication to between Computation Management cloud and the Manager is done via gRPC, while communication between Manager and Agent is done via Virtio Vsock. Vsock is used to send Agent events from the computation in the Agent to the Manager. The Manager then sends the events back to Computation Mangement cloud via gRPC, and these are visible to the end user.

+

Manager <> Agent#

+

When TEE is booted, and Agent is autmatically deployed and is used for outside communication with the enclave (via the API) and for computation orchestration (data and algorithm upload, start of the computation and retrieval of the result).

+

Agent is a gRPC server, and CLI is a gRPC client of the Agent. The Manager sends the Computation Manifest to the Agent via vsock and the Agent runs the computation, according to the Computation Manifest, while sending evnets back to manager on the status. The Manager then sends the events it receives from agent via vsock to Computation Mangement cloud through gRPC.

+

Setup and Test Manager <> Agent#

+
git clone https://github.com/ultravioletrs/cocos
+cd cocos
+
+
+

N.B. All relative paths in this document are relative to cocos repository directory.

+
+

QEMU-KVM#

+

QEMU-KVM is a virtualization platform that allows you to run multiple operating systems on the same physical machine. It is a combination of two technologies: QEMU and KVM.

+
    +
  • QEMU is an emulator that can run a variety of operating systems, including Linux, Windows, and macOS.
  • +
  • KVM is a Linux kernel module that allows QEMU to run virtual machines.
  • +
+

To install QEMU-KVM on a Debian based machine, run

+
sudo apt update
+sudo apt install qemu-kvm
+
+

Create img directory in cmd/manager. Create tmp directory in cmd/manager.

+

Add V-sock#

+

The necessary kernel modules must be loaded on the hypervisor.

+
sudo modprobe vhost_vsock
+ls -l /dev/vhost-vsock
+# crw-rw-rw- 1 root kvm 10, 241 Jan 16 12:05 /dev/vhost-vsock
+ls -l /dev/vsock
+# crw-rw-rw- 1 root root 10, 121 Jan 16 12:05 /dev/vsock
+
+

Prepare Cocos HAL#

+

Cocos HAL for Linux is framework for building custom in-enclave Linux distribution. Use the instructions in Readme. +Once the image is built copy the kernel and rootfs image to cmd/manager/img from buildroot/output/images/bzImage and buildroot/output/images/rootfs.cpio.gz respectively.

+

Test VM Creation#

+
cd cmd/manager
+
+sudo find / -name OVMF_CODE.fd
+# => /usr/share/OVMF/OVMF_CODE.fd
+OVMF_CODE=/usr/share/OVMF/OVMF_CODE.fd
+
+sudo find / -name OVMF_VARS.fd
+# => /usr/share/OVMF/OVMF_VARS.fd
+OVMF_VARS=/usr/share/OVMF/OVMF_VARS.fd
+
+KERNEL="img/bzImage"
+INITRD="img/rootfs.cpio.gz"
+
+qemu-system-x86_64 \
+    -enable-kvm \
+    -cpu EPYC-v4 \
+    -machine q35 \
+    -smp 4 \
+    -m 2048M,slots=5,maxmem=10240M \
+    -no-reboot \
+    -drive if=pflash,format=raw,unit=0,file=$OVMF_CODE,readonly=on \
+    -netdev user,id=vmnic,hostfwd=tcp::7020-:7002 \
+    -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= \
+    -device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=3 -vnc :0 \
+    -kernel $KERNEL \
+    -append "earlyprintk=serial console=ttyS0" \
+    -initrd $INITRD \
+    -nographic \
+    -monitor pty \
+    -monitor unix:monitor,server,nowait
+
+

Once the VM is booted press enter and on the login use username root.

+

Build and Run Agent#

+

Agent is started automatically in the VM.

+
# List running processes and use 'grep' to filter for processes containing 'agent' in their names.
+ps aux | grep cocos-agent
+# This command helps verify that the 'agent' process is running.
+# The output shows the process ID (PID), resource usage, and other information about the 'cocos-agent' process.
+# For example: 118 root     cocos-agent
+
+

We can also check if Agent is reachable from the host machine:

+
# Use netcat (nc) to test the connection to localhost on port 7020.
+nc -zv localhost 7020
+# Output:
+# nc: connect to localhost (::1) port 7020 (tcp) failed: Connection refused
+# Connection to localhost (127.0.0.1) 7020 port [tcp/*] succeeded!
+
+

Conclusion#

+

Now you are able to use Manager with Agent. Namely, Manager will create a VM with a separate OVMF variables file on manager /run request.

+

OVMF#

+

We need Open Virtual Machine Firmware. OVMF is a port of Intel's tianocore firmware - an open source implementation of the Unified Extensible Firmware Interface (UEFI) - used by a qemu virtual machine. We need OVMF in order to run virtual machine with focal-server-cloudimg-amd64. When we install QEMU, we get two files that we need to start a VM: OVMF_VARS.fd and OVMF_CODE.fd. We will make a local copy of OVMF_VARS.fd since a VM will modify this file. On the other hand, OVMF_CODE.fd is only used as a reference, so we only record its path in an environment variable.

+
sudo find / -name OVMF_CODE.fd
+# => /usr/share/OVMF/OVMF_CODE.fd
+MANAGER_QEMU_OVMF_CODE_FILE=/usr/share/OVMF/OVMF_CODE.fd
+
+sudo find / -name OVMF_VARS.fd
+# => /usr/share/OVMF/OVMF_VARS.fd
+MANAGER_QEMU_OVMF_VARS_FILE=/usr/share/OVMF/OVMF_VARS.fd
+
+

NB: we set environment variables that we will use in the shell process where we run manager.

+

Deployment#

+

To start the service, execute the following shell script (note a server needs to be running see here):

+
# download the latest version of the service
+go get github.com/ultravioletrs/cocos
+
+cd $GOPATH/src/github.com/ultravioletrs/cocos
+
+# compile the manager
+make manager
+
+# copy binary to bin
+make install
+
+# set the environment variables and run the service
+MANAGER_GRPC_URL=localhost:7001
+MANAGER_LOG_LEVEL=debug \
+MANAGER_QEMU_USE_SUDO=false \
+MANAGER_QEMU_ENABLE_SEV=false \
+./build/cocos-manager
+
+

To enable AMD SEV support, start manager like this

+
MANAGER_GRPC_URL=localhost:7001
+MANAGER_LOG_LEVEL=debug \
+MANAGER_QEMU_USE_SUDO=true \
+MANAGER_QEMU_ENABLE_SEV=true \
+MANAGER_QEMU_SEV_CBITPOS=51 \
+./build/cocos-manager
+
+

Verifying VM Launch#

+

NB: To verify that the manager successfully launched the VM, you need to open two terminals on the same machine. In one terminal, you need to launch go run main.go (with the environment variables of choice) and in the other, you can run the verification commands.

+

To verify that the manager launched the VM successfully, run the following command:

+
ps aux | grep qemu-system-x86_64
+
+

You should get something similar to this

+
darko     324763 95.3  6.0 6398136 981044 ?      Sl   16:17   0:15 /usr/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 4096M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -nographic -monitor pty
+
+

If you run a command as sudo, you should get the output similar to this one

+
root       37982  0.0  0.0   9444  4572 pts/0    S+   16:18   0:00 sudo /usr/local/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 4096M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -object sev-guest,id=sev0,cbitpos=51,reduced-phys-bits=1 -machine memory-encryption=sev0 -nographic -monitor pty
+root       37989  122 13.1 5345816 4252312 pts/0 Sl+  16:19   0:04 /usr/local/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 4096M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -object sev-guest,id=sev0,cbitpos=51,reduced-phys-bits=1 -machine memory-encryption=sev0 -nographic -monitor pty
+
+

The two processes are due to the fact that we run the command /usr/bin/qemu-system-x86_64 as sudo, so there is one process for sudo command and the other for /usr/bin/qemu-system-x86_64.

+

Troubleshooting#

+

If the ps aux | grep qemu-system-x86_64 give you something like this

+
darko      13913  0.0  0.0      0     0 pts/2    Z+   20:17   0:00 [qemu-system-x86] <defunct>
+
+

means that the a QEMU virtual machine that is currently defunct, meaning that it is no longer running. More precisely, the defunct process in the output is also known as a "zombie" process.

+

You can troubleshoot the VM launch procedure by running directly qemu-system-x86_64 command. When you run manager with MANAGER_LOG_LEVEL=info env var set, it prints out the entire command used to launch a VM. The relevant part of the log might look like this

+
{"level":"info","message":"/usr/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 4096M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -nographic -monitor pty","ts":"2023-08-14T18:29:19.2653908Z"}
+
+

You can run the command - the value of the "message" key - directly in the terminal:

+
/usr/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 4096M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -nographic -monitor pty
+
+

and look for the possible problems. This problems can usually be solved by using the adequate env var assignments. Look in the manager/qemu/config.go file to see the recognized env vars. Don't forget to prepend MANAGER_QEMU_ to the name of the env vars.

+

Kill qemu-system-x86_64 Processes#

+

To kill any leftover qemu-system-x86_64 processes, use

+
pkill -f qemu-system-x86_64
+
+

The pkill command is used to kill processes by name or by pattern. The -f flag to specify that we want to kill processes that match the pattern qemu-system-x86_64. It sends the SIGKILL signal to all processes that are running qemu-system-x86_64.

+

If this does not work, i.e. if ps aux | grep qemu-system-x86_64 still outputs qemu-system-x86_64 related process(es), you can kill the unwanted process with kill -9 <PID>, which also sends a SIGKILL signal to the process.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 0000000..e37e33e --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"What is CocosAI","text":"

CocosAI (Confidential Computing System for AI) is a SW system for enabling confidential and privacy-preserving AI/ML, i.e. execution of model training and algorithm inference on confidential data sets. Privacy-preservation is considered a \u201choly grail\u201d of AI. It opens many possibilities, among which is a collaborative, trustworthy AI.

CocosAI leverages Confidential Computing, a novel paradigm based on specialized HW CPU extensions for producting secure encrypted enclaves in memory (Trusted Execution Enviroments, or TEEs), thus isloalting confidential data and programs from the rest of the SW running on the hos

The final product enables data scientists to train AI and ML models on confidential data that is never revealed, and can be used for Secure Multi-Party Computation (SMPC). AI/ML on combined data sets that come from different sources will unlock huge value.

"},{"location":"#features","title":"Features","text":"

CoCoS.ai is enabling the following features:

  • TEE enablement, deployment and monitoring
  • In-enclave agent, netowrking controller and other system software
  • Encrypted asynchronous data transfer and result delivery
  • API for programmable platform manipulation
  • HW and SW supported attestation with verification tools
  • CLI for system interaction
"},{"location":"#license","title":"License","text":"

CocosAI is published under liberal Apache-2.0 open-source license.

"},{"location":"#github","title":"GitHub","text":"

CcosAI can be downlaoded from its GitHub repository

"},{"location":"agent/","title":"Agent","text":"

The agent is responsible for the life cycle of the computation, i.e., running the computation and sending events about the status of the computation within the TEE. The agent is found inside the VM (TEE), and each computation within the TEE has its own agent. When a computation run request is sent from from the manager, manager creates a VM where the agent is found and sends the computation manifest to the agent.

"},{"location":"agent/#agent-events","title":"Agent Events","text":"

As the computation in the agent undergoes different operations, it sends events to the manager so that the user can monitor the computation from either the UI or other client. Events sent to the manager include computation running, computation finished, computation failed, and computation stopped.

"},{"location":"agent/#vsock-connection-between-agent-manager","title":"Vsock Connection Between Agent & Manager","text":"

Agent sends agent events to the manager via vsock. The manager listens to the vsock and forwards the events via gRPC. The agent events are used to show the status of the computation inside the TEE so that a user can be aware of what is happening inside the TEE.

"},{"location":"agent/#security","title":"Security","text":"

To run a computation in the agent, a signed certificate is required. The certificate is used to verify the user who is running the computation. The certificate is sent to the agent by the manager, and the agent verifies the certificate before running the computation.

"},{"location":"architecture/","title":"Architecture","text":"

CocosAI system is running on the host, and it's main goal is to enable:

  • Programatic creation of enclaves (TEEs)
  • Gest OS and system enviroment withn the enclave VMs
  • Monitoring of enclaves
  • In-enclave SW manager agent
  • Ectyped data trensfer into the enclave and computation execution
  • Result retrieval via encrypted channel to an authorized party
  • Providing of HW measurement and attestation report
  • Enablement of vTPM and DICE integrity checks (root chain of trust) in order to ensure secure boot of the TEEs

These features are implemented by several independed components of CocosAI system:

  1. Manager
  2. Agent
  3. EOS (Enclave Operating System)
  4. CLI

N.B. CocosAI open-source project does not provide Computation Management service. It is usually a cloud component, used to define a Computation (i.e. define computation metadata, like participant list, algorithm and data providers, result recipients, etc...). Ultraviolet provide commercial product Prism, a multi-party computation platform, that implements multi-tenant and scalable Computation Management service, running in the cloud or on premise, and capable to connect and control CocosAI system running on the TEE host.

"},{"location":"architecture/#manager","title":"Manager","text":"

Manager is a gRPC client that listens to requests sent through gRPC and sends them to Agent via vsock. Manager creates a secure enclave and loads the computation where the agent resides. The connection between Manager and Agent is through vsock, through which channel agent sends events periodically to manager, who forwards these via gRPC.

"},{"location":"architecture/#agent","title":"Agent","text":"

Agent defines firmware which goes into the TEE and is used to control and monitor computation within TEE and enable secure and encrypted communication with outside world (in order to fetch the data and provide the result of the computation). The Agent contains a gRPC server that listens for requests from gRPC clients. Communication between the Manager and Agent is done via vsock. The Agent sends events to the Manager via vsock, which then forwards these via gRPC. Agent contains a gRPC server that exposes useful functions that can be accessed by other gRPC clients such as the CLI.

"},{"location":"architecture/#eos","title":"EOS","text":"

EOS, or Enclave Operating System, is ...

"},{"location":"architecture/#cli","title":"CLI","text":"

CoCoS CLI is used to access the agent within the secure enclave. CLI communicates to agent using gRPC, with funcitons such as algo to provide the algorithm to be run, data to provide the data to be used in the computation, and run to start the computation. It also has functions to fetch and validate the attestation report of the enclave.

For more information on CLI, please refer to CLI docs.

"},{"location":"attestation/","title":"Attestation","text":"

Remote attestation is a process in which one side (the attester) collects information about itself and sends that information to the client (or the relying party) so that the relying party can verify the attester. The successful verification proves to the relying party that the secure virtual machine (SVM) runs the expected code on the expected hardware and is configured correctly. If the attester is deemed trustworthy, the relying party will send confidential code/data to the attester. This information implies that a secure channel needs to be formed between the attester and the relaying party. The secure channel is created using attested TLS.

Cocos has two software components that represent the attester and the relying party:

  1. The Agent - software application that is running inside the HAL. It is responsible for fetching the attestation report and running the computation.
  2. Cocos CLI - a command-line application running on the machines of each Secure Multiparty Computation (SMPC) member. It verifies the attestation report and sends confidential code/data to the Agent.
"},{"location":"attestation/#what-are-the-parts-of-the-attestation-report","title":"What are the parts of the attestation report?","text":"

One of the essential parts of the attestation report is the measurement. The measurement represents the hash of the entire SVM or the hash of the HAL. This way, the measurement provides a way for the client to verify the contents of the entire SVM.

Along with the measurement, the attestation report provides additional information about the booted SVM and underlying hardware, such as the policy with which the SVM was booted and the SNP firmware's trusted computing base (TCB) version.

The AMD SEV-SNP attestation report can also be filled with arbitrary data. The width of this data field is 512 bits, and it is called report data. The report data content is provided by the Agent to the ASP every time the attestation report is generated.

The last part of the report is the signature. The hardware signs the AMD SEV-SNP attestation report using the Versioned Chip Endorsement Key (VCEK). VCEK is derived from chip unique secrets and the current SNP firmware TCB. The signature is verified by obtaining the certificate for the VCEK from the AMD Key Distribution System (KDS). By verifying the signature, the relying party can be sure that the SVM is running on genuine AMD hardware and that the AMD Secure Processor (ASP) generated the attestation report.

"},{"location":"attestation/#how-is-the-attestation-report-fetched","title":"How is the attestation report fetched?","text":"

The Agent is responsible for fetching the attestation report from the SVM. This procedure is safe because the Kernel and the ASP can exchange encrypted messages that can only be decrypted by the Kernel and the ASP. The keys used for the encryption/decryption are inserted by the ASP into the memory of the SVM during boot, thus ensuring that only the ASP and the SVM have the keys for safe communication.

"},{"location":"attestation/#attested-tls","title":"Attested TLS","text":"

For the relying party to send confidential data or code to the Agent, a secure channel must be established between them. This is done using attested TLS, which is a TLS connection where the server's certificate is extended with the attestation report. The SVM is the server in Cocos. The Agent generates a self-signed x.509 certificate extended with the attestation report. When fetching the attestation report, the Agent inserts the hash of the public key into it using the field report data. The whole process can be seen in the below picture. The green color represents the trusted part of the system, while the red is untrusted.

The relying party uses the Cocos CLI to verify the self-signed certificate and the attestation report that is part of it. Successful verification proves to the relying party that the certificate is generated inside the SVM because the certificate's public key is part of the attestation report.

"},{"location":"cli/","title":"Agent CLI","text":"

The CLI allows you to perform various tasks related to the computation and management of algorithms and datasets. The CLI is a gRPC client for the agent service.

"},{"location":"cli/#build","title":"Build","text":"

To build the CLI, follow these steps:

  1. Clone the repository: go get github.com/ultravioletrs/cocos.
  2. Navigate to the project root: cd cocos.
  3. Build the CLI binary: make cli.
"},{"location":"cli/#usage","title":"Usage","text":""},{"location":"cli/#set-agent-url","title":"Set Agent URL","text":"
export AGENT_GRPC_URL=<agent_host:agent_host>\n
"},{"location":"cli/#upload-algorithm","title":"Upload Algorithm","text":"

To upload an algorithm, use the following command:

./build/cocos-cli algo /path/to/algorithm\n
"},{"location":"cli/#upload-dataset","title":"Upload Dataset","text":"

To upload a dataset, use the following command:

./build/cocos-cli data /path/to/dataset.csv\n
"},{"location":"cli/#retrieve-result","title":"Retrieve Result","text":"

To retrieve the computation result, use the following command:

./build/cocos-cli result\n
"},{"location":"cli/#installation","title":"Installation","text":"

To install the CLI locally, i.e. for the current user:

Run make install-cli.

"},{"location":"cli/#notes","title":"Notes","text":"
  • The CLI supports various configuration flags and options
  • Use the --help flag with any command to see additionalinformation
  • The CLI uses gRPC for communication with the Agent service
  • All traffic between CLI and the TEE is encrypted via mutual TLS
"},{"location":"computation/","title":"Computation","text":"

Computation in CocosAI is any execution of a program (Algorithm) or an data set (Data), that can be one data file, or a lot of files comping from different parties.

Computations are multi-party, meaning that program and data providers can be different parties that do not want to expose their intellectual property to other parties participating in the computation.

Computation is a structure that holds all the necessary information needed to execute the computation securely (list of participants, execution backend - i.e. where computation will be executed, role of each participant, cryptographic certificates, etc...).

"},{"location":"computation/#computation-roles","title":"Computation Roles","text":"

Computation is multi-party, i.e. has multiple participants. Each of the users that participate in the computation can have one of the follwoing roles:

  1. Computation Owner - user that created the Computation and that defines who will participate in it and with wich role (by inviting other users to the Computation)
  2. Algorithm Provider - user that will provide th actual program to be executed
  3. Data Provider - user that will provide a data on which algorithm will be executed, i.e. data which algorithm will process
  4. Result Recipient - user that will recieve result after the processing

One user can have several roles - for example, Algorithm Provider can also be a Result Recipient.

"},{"location":"computation/#computation-manifest","title":"Computation Manifest","text":"

Computation Manifest represent that Computation description and is sent upon run command to the Manager as a JSON.

Manager fetches the Computation Manifest and sends it into the TEE to Agent, via vsock.

The first thing that Agent does upon boot, is that it fetches the Computation Manifest and reads it. For this Manifest, Agent understands who are the participants in the computation adn with wich role, i.e. from whom it can accept the connections and what data they will send. Agent also learns from the Manifest what algorithm is used and how many datasets will be provided. This way it knows when it received all necessary files to start the execution. Finally, Agent learns from the Manifest to whom it needs to send the Result of the computation.

"},{"location":"developer-guide/","title":"Developer Guide","text":""},{"location":"developer-guide/#getting-cocos","title":"Getting CoCos","text":"

CoCos is found on the CoCos repository. You should fork the repository in order to make changes to the repository. After forking the repository, you can clone it as follows:

git clone <forked repository> $SOMEPATH/cocos\ncd $SOMEPATH/cocos\n
"},{"location":"developer-guide/#building","title":"Building","text":""},{"location":"developer-guide/#prerequisites","title":"Prerequisites","text":"
  • Protocol Buffers
  • Golang
"},{"location":"developer-guide/#build-all-services","title":"Build All Services","text":"

Use the GNU Make tool to build all CoCos services: make Build artifacts will be put in the build directory.

"},{"location":"developer-guide/#building-hal","title":"Building HAL","text":"

To build the custom linux image that will host agent, run:

git clone git@github.com:buildroot/buildroot.git\ncd buildroot\nmake BR2_EXTERNAL=../cocos/hal/linux cocos_defconfig\nmake menuconfig #optional for additional configuration\nmake\n
"},{"location":"developer-guide/#testing-hal-image","title":"Testing HAL image","text":""},{"location":"developer-guide/#enable-v-sock","title":"Enable V-Sock","text":"

The necessary kernel modules must be loaded on the hypervisor.

sudo modprobe vhost_vsock\nls -l /dev/vhost-vsock\n# crw-rw-rw- 1 root kvm 10, 241 Jan 16 12:05 /dev/vhost-vsock\nls -l /dev/vsock\n# crw-rw-rw- 1 root root 10, 121 Jan 16 12:05 /dev/vsock\n
"},{"location":"developer-guide/#launch-the-vm","title":"Launch the VM","text":"

To launch the virtual machine containing agent for testing purposes, run:

sudo find / -name OVMF_CODE.fd\n# => /usr/share/OVMF/OVMF_CODE.fd\nOVMF_CODE=/usr/share/OVMF/OVMF_CODE.fd\n\nsudo find / -name OVMF_VARS.fd\n# => /usr/share/OVMF/OVMF_VARS.fd\nOVMF_VARS=/usr/share/OVMF/OVMF_VARS.fd\n\nKERNEL=\"buildroot/output/images/bzImage\"\nINITRD=\"buildroot/output/images/rootfs.cpio.gz\"\n\nqemu-system-x86_64 \\\n    -enable-kvm \\\n    -cpu EPYC-v4 \\\n    -machine q35 \\\n    -smp 4 \\\n    -m 2048M,slots=5,maxmem=10240M \\\n    -no-reboot \\\n    -drive if=pflash,format=raw,unit=0,file=$OVMF_CODE,readonly=on \\\n    -netdev user,id=vmnic,hostfwd=tcp::7020-:7002 \\\n    -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= \\\n    -device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=3 -vnc :0 \\\n    -kernel $KERNEL \\\n    -append \"earlyprintk=serial console=ttyS0\" \\\n    -initrd $INITRD \\\n    -nographic \\\n    -monitor pty \\\n    -monitor unix:monitor,server,nowait\n

The default password is root.

"},{"location":"developer-guide/#testing-agent-independently","title":"Testing Agent Independently","text":"

Agent once started will wait to receive its configuration via v-sock. For testing purposes you can use the script in cocos/test/manual/agent-config. This script sends agent config and also receives logs and events from agent. Once the VM is launched you can send config including computation manifest to agent as follows:

cd cocos\ngo run ./test/manual/agent-config/main.go\n
"},{"location":"developer-guide/#testing-manager","title":"Testing Manager","text":"

Manager is a gRPC client and needs gRPC sever to connect to. We have an example server for testing purposes in test/manager-server. Run the server as follows:

go run ./test/manager-server/main.go

"},{"location":"developer-guide/#run-manager","title":"Run Manager","text":"

Create two directories in cocos/cmd/manager, the directories are img and tmp. Copy rootfs.cpio.gz and bzImage from the buildroot output directory files to cocos/cmd/manager/img.

Next run manager client.

cd cmd/manager\nMANAGER_GRPC_URL=localhost:7001 MANAGER_LOG_LEVEL=debug MANAGER_QEMU_USE_SUDO=false  MANAGER_QEMU_ENABLE_SEV=false MANAGER_QEMU_OVMF_CODE_FILE=/usr/share/edk2/x64/OVMF_CODE.fd MANAGER_QEMU_OVMF_VARS_FILE=/usr/share/edk2/x64/OVMF_VARS.fd go run main.go\n

This will result in manager sending a whoIam request to manager-server. Manager server will then launch a VM with agent running and having received the computation manifest.

"},{"location":"developer-guide/#runnung-tests","title":"Runnung Tests","text":"

To run all of the tests you can execute: make test

"},{"location":"developer-guide/#protobuf","title":"Protobuf","text":"

If you've made any changes to .proto files, you should call protoc command prior to compiling individual microservices.

To do this by hand, execute: make protoc

"},{"location":"developer-guide/#troubleshooting","title":"Troubleshooting","text":"

If you run ps aux | grep qemu-system-x86_64 and it returns give you something like this:

sammy      13913  0.0  0.0      0     0 pts/2    Z+   20:17   0:00 [qemu-system-x86] <defunct>\n

means that the a QEMU virtual machine that is currently defunct, meaning that it is no longer running. More precisely, the defunct process in the output is also known as a \"zombie\" process.

"},{"location":"developer-guide/#kill-qemu-system-x86_64-processes","title":"Kill qemu-system-x86_64 Processes","text":"

To kill any leftover qemu-system-x86_64 processes, use pkill -f qemu-system-x86_64 The pkill command is used to kill processes by name or by pattern. The -f flag to specify that we want to kill processes that match the pattern qemu-system-x86_64. It sends the SIGKILL signal to all processes that are running qemu-system-x86_64.

If this does not work, i.e. if ps aux | grep qemu-system-x86_64 still outputs qemu-system-x86_64 related process(es), you can kill the unwanted process with kill -9 <PID>, which also sends a SIGKILL signal to the process.

"},{"location":"getting-started/","title":"Getting Started","text":""},{"location":"getting-started/#prerequisites","title":"Prerequisites","text":"

Before proceeding install the following requirements. - Golang (version 1.21.6)

"},{"location":"getting-started/#getting-cocos","title":"Getting CoCos","text":"

Get the cocos repository: git clone https://github.com/ultravioletrs/cocos.git

"},{"location":"getting-started/#hal","title":"HAL","text":"

Get the hardware abstraction layer from the releases on the cocos repository. Two files will be required: - rootfs.cpio.gz - Initramfs - bzImage - Kernel

Create two directories in cocos/cmd/manager, the directories are img and tmp. Copy the downloaded files to cocos/cmd/manager/img.

"},{"location":"getting-started/#starting-manager-server","title":"Starting Manager Server","text":"

Manager is a gRPC client and needs gRPC sever to connect to. We have an example server for testing purposes in test/manager-server. Run the server as follows:

go run ./test/manager-server/main.go

the output should be simillar to this: {\"time\":\"2024-03-19T12:27:46.542638146+03:00\",\"level\":\"INFO\",\"msg\":\"manager_test_server service gRPC server listening at :7001 without TLS\"}

"},{"location":"getting-started/#running-manager","title":"Running Manager","text":"

Next we need to start manager. But first we'll need to install some prerequisites.

"},{"location":"getting-started/#vsock","title":"Vsock","text":"

Virtio-vsock is a host/guest communications device. It allows applications in the guest and host to communicate. In this case, it is used to communicate between manager and agent. To enable it run the following on the host: sudo modprobe vhost_vsock

to confirm that it is enabled run: ls -l /dev/vsock and ls -l /dev/vhost-vsock the output should be simillar to this respectively: crw-rw-rw- 1 root root 10, 121 Mar 18 14:01 /dev/vsock and crw-rw-rw- 1 root kvm 10, 241 Mar 18 14:01 /dev/vhost-vsock

"},{"location":"getting-started/#ovmf","title":"OVMF","text":"

Find the ovmf code file:

sudo find / -name OVMF_CODE.fd\n

The output will be simillar to this:

/usr/share/edk2/x64/OVMF_CODE.fd\n/usr/share/edk2/ia32/OVMF_CODE.fd\n

Find the ovmf vars file:

sudo find / -name OVMF_VARS.fd\n

the output will be simillar to this

/usr/share/edk2/x64/OVMF_VARS.fd\n/usr/share/edk2/ia32/OVMF_VARS.fd\n
"},{"location":"getting-started/#run","title":"Run","text":"

When manager connects to the server, it sends a whoAmI request after which the server sends a computation manifest. In response manager will sends logs and events from the computation both from manager and agent. To start run:

cd cmd/manager\nMANAGER_GRPC_URL=localhost:7001 MANAGER_LOG_LEVEL=debug MANAGER_QEMU_USE_SUDO=false  MANAGER_QEMU_ENABLE_SEV=false MANAGER_QEMU_OVMF_CODE_FILE=/usr/share/edk2/x64/OVMF_CODE.fd MANAGER_QEMU_OVMF_VARS_FILE=/usr/share/edk2/x64/OVMF_VARS.fd go run main.go\n

The output on manager will be simillar to this:

{\"time\":\"2024-03-19T12:38:53.647541406+03:00\",\"level\":\"INFO\",\"msg\":\"/usr/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 2048M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/edk2/x64/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=/usr/share/edk2/x64/OVMF_VARS.fd -netdev user,id=vmnic,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,addr=0x2,romfile= -device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=3 -vnc :0 -kernel img/bzImage -append \\\"earlyprintk=serial console=ttyS0\\\" -initrd img/rootfs.cpio.gz -nographic -monitor pty\"}\n{\"time\":\"2024-03-19T12:39:07.819774273+03:00\",\"level\":\"INFO\",\"msg\":\"Method Run for computation took 14.169748744s to complete\"}\n{\"time\":\"2024-03-19T12:39:07.821687259+03:00\",\"level\":\"INFO\",\"msg\":\"Agent Log/Event, Computation ID: 1, Message: agent_log:{message:\\\"Method Run for computation 1 took 51.066\u00b5s to complete without errors.\\\"  computation_id:\\\"1\\\"  level:\\\"INFO\\\"  timestamp:{seconds:1710841147  nanos:818774262}}\"}\n{\"time\":\"2024-03-19T12:39:07.821994067+03:00\",\"level\":\"INFO\",\"msg\":\"Agent Log/Event, Computation ID: 1, Message: agent_log:{message:\\\"Transition: receivingAlgorithms -> receivingAlgorithms\\\\n\\\"  computation_id:\\\"1\\\"  level:\\\"DEBUG\\\"  timestamp:{seconds:1710841147  nanos:819067478}}\"}\n{\"time\":\"2024-03-19T12:39:07.822053853+03:00\",\"level\":\"INFO\",\"msg\":\"Agent Log/Event, Computation ID: 1, Message: agent_event:{event_type:\\\"receivingAlgorithms\\\"  timestamp:{seconds:1710841147  nanos:819118886}  computation_id:\\\"1\\\"  originator:\\\"agent\\\"  status:\\\"in-progress\\\"}\"}\n{\"time\":\"2024-03-19T12:39:07.822605252+03:00\",\"level\":\"INFO\",\"msg\":\"Agent Log/Event, Computation ID: 1, Message: agent_log:{message:\\\"agent service gRPC server listening at :7002 without TLS\\\"  computation_id:\\\"1\\\"  level:\\\"INFO\\\"  timestamp:{seconds:1710841147  nanos:819759020}}\"}\n

The output on manager test server will be simillar to this:

{\"time\":\"2024-03-19T12:27:46.542638146+03:00\",\"level\":\"INFO\",\"msg\":\"manager_test_server service gRPC server listening at :7001 without TLS\"}\n{\"time\":\"2024-03-19T12:38:53.64961785+03:00\",\"level\":\"DEBUG\",\"msg\":\"received who am on ip address [::1]:48592\"}\nreceived whoamI\n&{}\nreceived agent event\n&{event_type:\"vm-provision\" timestamp:{seconds:1710841133 nanos:649982672} computation_id:\"1\" originator:\"manager\" status:\"starting\"}\nreceived agent event\n&{event_type:\"vm-provision\" timestamp:{seconds:1710841133 nanos:650082447} computation_id:\"1\" originator:\"manager\" status:\"in-progress\"}\nreceived agent event\n&{event_type:\"vm-provision\" timestamp:{seconds:1710841147 nanos:819724344} computation_id:\"1\" originator:\"manager\" status:\"complete\"}\nreceived runRes\n&{agent_port:\"46693\" computation_id:\"1\"}\nreceived agent log\n&{message:\"Method Run for computation 1 took 51.066\u00b5s to complete without errors.\" computation_id:\"1\" level:\"INFO\" timestamp:{seconds:1710841147 nanos:818774262}}\nreceived agent log\n&{message:\"Transition: receivingAlgorithms -> receivingAlgorithms\\n\" computation_id:\"1\" level:\"DEBUG\" timestamp:{seconds:1710841147 nanos:819067478}}\nreceived agent event\n&{event_type:\"receivingAlgorithms\" timestamp:{seconds:1710841147 nanos:819118886} computation_id:\"1\" originator:\"agent\" status:\"in-progress\"}\nreceived agent log\n&{message:\"agent service gRPC server listening at :7002 without TLS\" computation_id:\"1\" level:\"INFO\" timestamp:{seconds:1710841147 nanos:819759020}}\n

From the logs we see agent has been bound to port 48592 which we can use with agent cli to send the algorithm, datasets and retrieve results. In this case the AGENT_GRPC_URL will be localhost:48592. To test agent proceed to CLI

"},{"location":"hal/","title":"Hardware Abstraction Layer (HAL)","text":"

HAL is a layer of programming that allows the software to interact with the hardware device at a general level rather than at the detailed hardware level. Cocos uses HAL and AMD SEV-SNP as an abstraction layer for confidential computing.

AMD SEV-SNP creates secure virtual machines (SVMs). VMs are usually used to run an operating system (e.g., Ubuntu and its applications). To avoid using a whole OS, HAL uses:

  • Linux kernel v6.6 - vmlinuz archive with the standard Linux kernel v6.6 with support for AMD SEV.
  • File system - the initial RAM file system (initramfs) that is used as the root file system of the VM.

This way, applications can be executed in the SVM, and the whole HAL SVM is entirely in RAM, protected by SEV-SNP. Being a RAM-only SVM means that secrets that are kept in the SVM will be destroyed when the SVM stops working.

"},{"location":"hal/#how-is-hal-constructed","title":"How is HAL constructed?","text":"

HAL is made using the tool Buildroot. Buildroot is used to create efficient, embedded Linux systems, and we use it to create the compressed image of the kernel (vmlinuz) and the initial file system (initramfs).

HAL configuration for Buildroot also includes Python runtime and agent software support. You can read more about the Agent software here.

"},{"location":"hal/#how-does-it-work","title":"How does it work?","text":"

HAL is combined with AMD SEV-SNP to provide a fully encrypted VM that can be verified using remote attestation. You can read more about the attestation process here.

Cocos uses QEMU and Open Virtual Machine Firmware (OVMF) to boot the confidential VM. During boot with SEV-SNP, the AMD Secure Processor (AMD SP) measures (calculates the hash) of the contents of the VM to insert that hash into the attestation report. This measurement is proof of what is currently running inside the VM. The problem with SEV is that it only measures the Open Virtual Machine Firmware (OVMF). To solve this, we have built OVMF so that OVMF contains hashes of the vmlinuz and initrams. Once the OVMF is loaded, it will load the vmlinuz and initramfs into memory, but it will continue the boot process only if the hashes of the vmlinuz and initramfs match the hashes stored in OVMF. This way, the attestation report will contain the measurement of OVMF, with the hashes, and OVMF will guarantee that the correct kernel and file system are booted. The whole process can be seen in the following diagram. The green color represents the trusted part of the system, while the red is untrusted:

This process guarantees that the whole VM is secure and can be verified.

After the kernel boots, the agent is started and ready for work.

"},{"location":"manager/","title":"Manager","text":"

Manager runs on the TEE-capable host (AMD SEV-SNP, Intel SGX or Intel TDX) and has 2 main roles:

  1. To deploy the well-prepared TEE upon the start command and upload the necessary configuration into it (command line arguments, TLS certificates, etc...)
  2. To monitor deployed TEE and provide remot logs

Manager expsoses and API for control, based on gRPC, and is controlled by Computation Management service. Manager acts as the client of Computation Management service and connects to it upon the start via TLS-encoded gRPC connection.

Computation Management service is used to to cnfigure computation metadata. Once a computation is created by a user and the invited users have uploaded their public certificates (used later for identification and data exchange in the enclave), a run request is sent. The Manager is responsible for creating the TEE in which computation will be ran and managing the computation lifecycle.

Communication to between Computation Management cloud and the Manager is done via gRPC, while communication between Manager and Agent is done via Virtio Vsock. Vsock is used to send Agent events from the computation in the Agent to the Manager. The Manager then sends the events back to Computation Mangement cloud via gRPC, and these are visible to the end user.

"},{"location":"manager/#manager-agent","title":"Manager <> Agent","text":"

When TEE is booted, and Agent is autmatically deployed and is used for outside communication with the enclave (via the API) and for computation orchestration (data and algorithm upload, start of the computation and retrieval of the result).

Agent is a gRPC server, and CLI is a gRPC client of the Agent. The Manager sends the Computation Manifest to the Agent via vsock and the Agent runs the computation, according to the Computation Manifest, while sending evnets back to manager on the status. The Manager then sends the events it receives from agent via vsock to Computation Mangement cloud through gRPC.

"},{"location":"manager/#setup-and-test-manager-agent","title":"Setup and Test Manager <> Agent","text":"
git clone https://github.com/ultravioletrs/cocos\ncd cocos\n

N.B. All relative paths in this document are relative to cocos repository directory.

"},{"location":"manager/#qemu-kvm","title":"QEMU-KVM","text":"

QEMU-KVM is a virtualization platform that allows you to run multiple operating systems on the same physical machine. It is a combination of two technologies: QEMU and KVM.

  • QEMU is an emulator that can run a variety of operating systems, including Linux, Windows, and macOS.
  • KVM is a Linux kernel module that allows QEMU to run virtual machines.

To install QEMU-KVM on a Debian based machine, run

sudo apt update\nsudo apt install qemu-kvm\n

Create img directory in cmd/manager. Create tmp directory in cmd/manager.

"},{"location":"manager/#add-v-sock","title":"Add V-sock","text":"

The necessary kernel modules must be loaded on the hypervisor.

sudo modprobe vhost_vsock\nls -l /dev/vhost-vsock\n# crw-rw-rw- 1 root kvm 10, 241 Jan 16 12:05 /dev/vhost-vsock\nls -l /dev/vsock\n# crw-rw-rw- 1 root root 10, 121 Jan 16 12:05 /dev/vsock\n
"},{"location":"manager/#prepare-cocos-hal","title":"Prepare Cocos HAL","text":"

Cocos HAL for Linux is framework for building custom in-enclave Linux distribution. Use the instructions in Readme. Once the image is built copy the kernel and rootfs image to cmd/manager/img from buildroot/output/images/bzImage and buildroot/output/images/rootfs.cpio.gz respectively.

"},{"location":"manager/#test-vm-creation","title":"Test VM Creation","text":"
cd cmd/manager\n\nsudo find / -name OVMF_CODE.fd\n# => /usr/share/OVMF/OVMF_CODE.fd\nOVMF_CODE=/usr/share/OVMF/OVMF_CODE.fd\n\nsudo find / -name OVMF_VARS.fd\n# => /usr/share/OVMF/OVMF_VARS.fd\nOVMF_VARS=/usr/share/OVMF/OVMF_VARS.fd\n\nKERNEL=\"img/bzImage\"\nINITRD=\"img/rootfs.cpio.gz\"\n\nqemu-system-x86_64 \\\n    -enable-kvm \\\n    -cpu EPYC-v4 \\\n    -machine q35 \\\n    -smp 4 \\\n    -m 2048M,slots=5,maxmem=10240M \\\n    -no-reboot \\\n    -drive if=pflash,format=raw,unit=0,file=$OVMF_CODE,readonly=on \\\n    -netdev user,id=vmnic,hostfwd=tcp::7020-:7002 \\\n    -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= \\\n    -device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=3 -vnc :0 \\\n    -kernel $KERNEL \\\n    -append \"earlyprintk=serial console=ttyS0\" \\\n    -initrd $INITRD \\\n    -nographic \\\n    -monitor pty \\\n    -monitor unix:monitor,server,nowait\n

Once the VM is booted press enter and on the login use username root.

"},{"location":"manager/#build-and-run-agent","title":"Build and Run Agent","text":"

Agent is started automatically in the VM.

# List running processes and use 'grep' to filter for processes containing 'agent' in their names.\nps aux | grep cocos-agent\n# This command helps verify that the 'agent' process is running.\n# The output shows the process ID (PID), resource usage, and other information about the 'cocos-agent' process.\n# For example: 118 root     cocos-agent\n

We can also check if Agent is reachable from the host machine:

# Use netcat (nc) to test the connection to localhost on port 7020.\nnc -zv localhost 7020\n# Output:\n# nc: connect to localhost (::1) port 7020 (tcp) failed: Connection refused\n# Connection to localhost (127.0.0.1) 7020 port [tcp/*] succeeded!\n
"},{"location":"manager/#conclusion","title":"Conclusion","text":"

Now you are able to use Manager with Agent. Namely, Manager will create a VM with a separate OVMF variables file on manager /run request.

"},{"location":"manager/#ovmf","title":"OVMF","text":"

We need Open Virtual Machine Firmware. OVMF is a port of Intel's tianocore firmware - an open source implementation of the Unified Extensible Firmware Interface (UEFI) - used by a qemu virtual machine. We need OVMF in order to run virtual machine with focal-server-cloudimg-amd64. When we install QEMU, we get two files that we need to start a VM: OVMF_VARS.fd and OVMF_CODE.fd. We will make a local copy of OVMF_VARS.fd since a VM will modify this file. On the other hand, OVMF_CODE.fd is only used as a reference, so we only record its path in an environment variable.

sudo find / -name OVMF_CODE.fd\n# => /usr/share/OVMF/OVMF_CODE.fd\nMANAGER_QEMU_OVMF_CODE_FILE=/usr/share/OVMF/OVMF_CODE.fd\n\nsudo find / -name OVMF_VARS.fd\n# => /usr/share/OVMF/OVMF_VARS.fd\nMANAGER_QEMU_OVMF_VARS_FILE=/usr/share/OVMF/OVMF_VARS.fd\n

NB: we set environment variables that we will use in the shell process where we run manager.

"},{"location":"manager/#deployment","title":"Deployment","text":"

To start the service, execute the following shell script (note a server needs to be running see here):

# download the latest version of the service\ngo get github.com/ultravioletrs/cocos\n\ncd $GOPATH/src/github.com/ultravioletrs/cocos\n\n# compile the manager\nmake manager\n\n# copy binary to bin\nmake install\n\n# set the environment variables and run the service\nMANAGER_GRPC_URL=localhost:7001\nMANAGER_LOG_LEVEL=debug \\\nMANAGER_QEMU_USE_SUDO=false \\\nMANAGER_QEMU_ENABLE_SEV=false \\\n./build/cocos-manager\n

To enable AMD SEV support, start manager like this

MANAGER_GRPC_URL=localhost:7001\nMANAGER_LOG_LEVEL=debug \\\nMANAGER_QEMU_USE_SUDO=true \\\nMANAGER_QEMU_ENABLE_SEV=true \\\nMANAGER_QEMU_SEV_CBITPOS=51 \\\n./build/cocos-manager\n
"},{"location":"manager/#verifying-vm-launch","title":"Verifying VM Launch","text":"

NB: To verify that the manager successfully launched the VM, you need to open two terminals on the same machine. In one terminal, you need to launch go run main.go (with the environment variables of choice) and in the other, you can run the verification commands.

To verify that the manager launched the VM successfully, run the following command:

ps aux | grep qemu-system-x86_64\n

You should get something similar to this

darko     324763 95.3  6.0 6398136 981044 ?      Sl   16:17   0:15 /usr/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 4096M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -nographic -monitor pty\n

If you run a command as sudo, you should get the output similar to this one

root       37982  0.0  0.0   9444  4572 pts/0    S+   16:18   0:00 sudo /usr/local/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 4096M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -object sev-guest,id=sev0,cbitpos=51,reduced-phys-bits=1 -machine memory-encryption=sev0 -nographic -monitor pty\nroot       37989  122 13.1 5345816 4252312 pts/0 Sl+  16:19   0:04 /usr/local/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 4096M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -object sev-guest,id=sev0,cbitpos=51,reduced-phys-bits=1 -machine memory-encryption=sev0 -nographic -monitor pty\n

The two processes are due to the fact that we run the command /usr/bin/qemu-system-x86_64 as sudo, so there is one process for sudo command and the other for /usr/bin/qemu-system-x86_64.

"},{"location":"manager/#troubleshooting","title":"Troubleshooting","text":"

If the ps aux | grep qemu-system-x86_64 give you something like this

darko      13913  0.0  0.0      0     0 pts/2    Z+   20:17   0:00 [qemu-system-x86] <defunct>\n

means that the a QEMU virtual machine that is currently defunct, meaning that it is no longer running. More precisely, the defunct process in the output is also known as a \"zombie\" process.

You can troubleshoot the VM launch procedure by running directly qemu-system-x86_64 command. When you run manager with MANAGER_LOG_LEVEL=info env var set, it prints out the entire command used to launch a VM. The relevant part of the log might look like this

{\"level\":\"info\",\"message\":\"/usr/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 4096M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -nographic -monitor pty\",\"ts\":\"2023-08-14T18:29:19.2653908Z\"}\n

You can run the command - the value of the \"message\" key - directly in the terminal:

/usr/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 4096M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -nographic -monitor pty\n

and look for the possible problems. This problems can usually be solved by using the adequate env var assignments. Look in the manager/qemu/config.go file to see the recognized env vars. Don't forget to prepend MANAGER_QEMU_ to the name of the env vars.

"},{"location":"manager/#kill-qemu-system-x86_64-processes","title":"Kill qemu-system-x86_64 Processes","text":"

To kill any leftover qemu-system-x86_64 processes, use

pkill -f qemu-system-x86_64\n

The pkill command is used to kill processes by name or by pattern. The -f flag to specify that we want to kill processes that match the pattern qemu-system-x86_64. It sends the SIGKILL signal to all processes that are running qemu-system-x86_64.

If this does not work, i.e. if ps aux | grep qemu-system-x86_64 still outputs qemu-system-x86_64 related process(es), you can kill the unwanted process with kill -9 <PID>, which also sends a SIGKILL signal to the process.

"},{"location":"tee/","title":"TEE","text":"

A trusted execution environment (TEE) is a separate part of the main memory and the CPU that encrypts code/data and enables \"on the fly\" executions of the said encrypted code/data. One of the examples of TEEs is Intel Secure Guard Extensions (SGX) and AMD Secure Encrypted Virtualization (SEV).

"},{"location":"tee/#amd-sev","title":"AMD SEV","text":"

AMD SEV and its latest and most secure iteration, AMD Secure Encrypted Virtualization - Secure Nested Paging (SEV-SNP), is the AMD technology that isolates entire virtual machines (VMs). SEV-SNP encrypts the whole VM and provides confidentiality and integrity protection of the VM memory. This way, the hypervisor or any other application on the host machine cannot read the VM memory.

In CocosAI, we use an in-memory VM image called the Hardware Abstraction Layer (HAL). You can read more on HAL here.

One of the critical components of the SEV technology is the remote attestation. Remote attestation is a process in which one side (the attester) collects information about itself and sends that information to the client (or the relying party) for the relying party to assess the trustworthiness of the attester. If the attester is deemed trustworthy, the relying party will send confidential code/data or any secrets to the attester. You can read more on the attestation process here.

"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..3de02fd --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,58 @@ + + + + https://docs.cocos.ai/ + 2024-04-14 + daily + + + https://docs.cocos.ai/agent/ + 2024-04-14 + daily + + + https://docs.cocos.ai/architecture/ + 2024-04-14 + daily + + + https://docs.cocos.ai/attestation/ + 2024-04-14 + daily + + + https://docs.cocos.ai/cli/ + 2024-04-14 + daily + + + https://docs.cocos.ai/computation/ + 2024-04-14 + daily + + + https://docs.cocos.ai/developer-guide/ + 2024-04-14 + daily + + + https://docs.cocos.ai/getting-started/ + 2024-04-14 + daily + + + https://docs.cocos.ai/hal/ + 2024-04-14 + daily + + + https://docs.cocos.ai/manager/ + 2024-04-14 + daily + + + https://docs.cocos.ai/tee/ + 2024-04-14 + daily + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..b442f7a5390dda21925c2fb11a5ec7bbcd9a79b0 GIT binary patch literal 285 zcmV+&0pk82iwFp)?;B7_$)Cmh+iUwI zF8VMmB_dG6;)G{063s74t?Mc=5KLx9nTuCwM@~>ZimH>(LLVBAt-<|viy>yKw=T$S zT(&4}wi%@fYEawTUTTo0?DVNS^=;R;$DSpR+D>LilRSJB_|(pX_&umy<<6jfA^whI zJS3_Ps@Rc7Y-uS_9UBoK8Dc-xhGt`R_Of}JmpZ5A;0iI%P+GqPSDnv15b=^~*=vQs j)rL2kSR2x05^u9o8y3Moc + + + + + + + + + + + + + + + + + + + + + + + + TEE - Cocos + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + +

TEE#

+

A trusted execution environment (TEE) is a separate part of the main memory and the CPU that encrypts code/data and enables "on the fly" executions of the said encrypted code/data. One of the examples of TEEs is Intel Secure Guard Extensions (SGX) and AMD Secure Encrypted Virtualization (SEV).

+

AMD SEV#

+

AMD SEV and its latest and most secure iteration, AMD Secure Encrypted Virtualization - Secure Nested Paging (SEV-SNP), is the AMD technology that isolates entire virtual machines (VMs). SEV-SNP encrypts the whole VM and provides confidentiality and integrity protection of the VM memory. This way, the hypervisor or any other application on the host machine cannot read the VM memory.

+

In CocosAI, we use an in-memory VM image called the Hardware Abstraction Layer (HAL). You can read more on HAL here.

+

One of the critical components of the SEV technology is the remote attestation. Remote attestation is a process in which one side (the attester) collects information about itself and sends that information to the client (or the relying party) for the relying party to assess the trustworthiness of the attester. If the attester is deemed trustworthy, the relying party will send confidential code/data or any secrets to the attester. You can read more on the attestation process here.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file