8 ms·
Preventing IoT Edge Device Cloning
- imglorp 1y agoAWS Greengrass was a pain in the tail to use, but I feel they had several ideas to mitigate this problem at least: identity was managed centrally with certificate rotation. I'm pretty sure a captured device could not be cloned and continue to phone into the cloud. They had several other good ideas, maybe standard now, like device shadows, where intent is propagated towards the edge and state is propagated back to the cloud.
- tylerflick 1y agoI hate managing clients certs, but I doubt there’s a better way.
- evgpbfhnr 1y ago"How it works" https://realtimelogic.com/ba/doc/en/SoftTPM.html https://realtimelogic.com/ba/doc/en/SoftTPM.html I couldn't find "actual sources", but one of their github repo has this: https://github.com/RealTimeLogic/BAS/blob/main/examples/MakoServer/src/tpm.h https://github.com/RealTimeLogic/BAS/blob/main/examples/Mako... Which extracts to this .config file (looks like lua code, that creates a secret from PBKDF2 of... what? I couldn't find where secrets would come from here, but that repo obviously misses the interesting bindings; from the how it works link it looks like they're just hashing the SN to generate a pseudorandom key but I don't see why you couldn't just generate a key for neighboring devices by just faking the SN then...) local maxHash=pcall(function() ba.crypto.hash("sha512") end) and "sha512" or "sha256" local sfmt,jencode,jdecode,symmetric,PBKDF2,keyparams,sign,jwtsign,createkey,createcsr,sharkcert= string.format,ba.json.encode,ba.json.decode,ba.crypto.symmetric,ba.crypto.PBKDF2,ba.crypto.keyparams, ba.crypto.sign,require"jwt".sign,ba.create.key,ba.create.csr,ba.create.sharkcert local function setuser(ju,db,name,pwd) if pwd then if type(pwd) == "string" then pwd={pwd=pwd,roles={}} end db[name]=pwd else db[name]=nil end local ok,err=ju:set(db) if not ok then error(err,3) end end local function tpm(gpkey,upkey) local keys={} local function tpmGetKey(kname) local key=keys[kname] if not key then error(sfmt("ECC key %s not found",tostring(kname)),3) end return key end local function tpmSign(h,kname,op) return sign(h,tpmGetKey(kname),op) end local function tpmJwtsign(p,kname,op) return jwtsign(p,function(h) return sign(h,tpmGetKey(kname)) end,op) end local function tpmKeyparams(kname) return keyparams(tpmGetKey(kname)) end local function tpmCreatecsr(kname,...) return createcsr(tpmGetKey(kname),...) end local function tpmCreatekey(kname,op) if keys[kname] then error(sfmt("ECC key %s exists",kname),2) end op = op or {} if op.key and op.key ~= "ecc" then error("TPM can only create ECC keys",2) end local newOp={} for k,v in pairs(op) do newOp[k]=v end newOp.rnd=PBKDF2(maxHash,"@#"..kname,upkey,5,1024) local key=createkey(newOp) keys[kname]=key return true end local function tpmHaskey(kname) return keys[kname] and true or false end local function tpmSharkcert(kname,certdata) return sharkcert(certdata,tpmGetKey(kname)) end require"acme/engine".setTPM{jwtsign=tpmJwtsign,keyparams=tpmKeyparams,createcsr=tpmCreatecsr,createkey=tpmCreatekey,haskey=tpmHaskey} local t={} function t.haskey(k) return tpmHaskey(k) end function t.createkey(k,...) return tpmCreatekey(k,...) end function t.createcsr(k,...) return tpmCreatecsr(k,...) end function t.sign(h,k,o) return tpmSign(h,k,o) end function t.jwtsign(k,...) return tpmJwtsign(k,...) end function t.keyparams(k,...) return tpmKeyparams(k,...) end function t.sharkcert(k,...) return tpmSharkcert(k,...) end function t.globalkey(n,l) return PBKDF2(maxHash,n,gpkey,5,l) end function t.uniquekey(n,l) return PBKDF2(maxHash,n,upkey,5,l) end function t.jsonuser(k,global) k=PBKDF2("sha256","@#"..k,global and gpkey or upkey,6,1) local function enc(db) local iv=ba.rndbs(12) local gcmEnc=symmetric("GCM",k,iv) local cipher,tag=gcmEnc:encrypt(jencode(db),"PKCS7") return iv..tag..cipher end local function dec(encdb) if encdb and #encdb > 30 then local iv=encdb:sub(1,12) local tag=encdb:sub(13,28) local gcmDec=symmetric("GCM",k,iv) local db pcall(function() db=jdecode(gcmDec:decrypt(encdb:sub(29,-1),tag,"PKCS7")) end) if db then return db end end return nil,"Data corrupt" end local ju,db=ba.create.jsonuser(),{} return { users=function() local x={} for u in pairs(db) do table.insert(x,u) end return x end, setuser=function(name,pwd) setuser(ju,db,name,pwd) return enc(db) end, setdb=function(encdb) local d,err,ok=dec(encdb) if d then ok,err=ju:set(d) if ok then db=d return ok end end return nil,err end, getauth=function() return ju end } end ba.tpm=t end local klist={} return function(x) if true == x then local hf=ba.crypto.hash(maxHash) for _,k in ipairs(klist) do hf(k) end tpm(ba.crypto.hash(maxHash)(klist[1])(true),hf(true)) klist=nil return end table.insert(klist,x) end
- 3r7j6qzi9jvnve 1y agoThe user apparently needs to provide that through ba.tpm.uniquekey(), providing persistent random data that is device dependent: https://realtimelogic.com/ba/doc/?url=auxlua.html#ba_tpm_globalkey https://realtimelogic.com/ba/doc/?url=auxlua.html#ba_tpm_glo... I guess the rest still provide value by transforming whatever random seed into a proper certificate though.
- baybal2 1y ago[dead]
- mrbluecoat 1y ago> when attackers capture real devices, extract cryptographic keys or identifiers, and use them to build duplicates If they've captured the device, what if they don't clone it but use it directly instead?
- 4gotunameagain 1y agoIt is often the case that a device is stand-alone, doing its thing without input from a user. E.g. data collection or independent/remote process control.