blob: a77dc4764e918f561483016b83e123010bac5abd [file] [log] [blame]
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2014-2015 Regents of the University of California.
# Author: Jeff Thompson <jefft0@remap.ucla.edu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# A copy of the GNU Lesser General Public License is in the file COPYING.
import time
import json
from pyndn import Name, Face, Interest, Data, ThreadsafeFace
from pyndn import KeyLocator, KeyLocatorType
from base_node import BaseNode
from hmac_helper import HmacHelper
from pyndn.security.security_exception import SecurityException
from pyndn.util import Blob
try:
import asyncio
except ImportError:
import trollius as asyncio
def dump(*list):
result = ""
for element in list:
result += (element if type(element) is str else repr(element)) + " "
print(result)
class Device(BaseNode):
def __init__(self,configFileName):
super(Device, self).__init__(configFileName=configFileName)
self._deviceSerial = self.getSerial()
self._callbackCount = 0
self._symKey = "symmetricKeyForBootstrapping"
self._category = "sensors"
self._id = "T9273659"
self._hmacHelper = HmacHelper(self._symKey)
def expressBootstrapInterest(self):
#generate bootstrap name /home/controller/bootstrap/<device-parameters>
bootstrapName = Name(self._bootstrapPrefix)
deviceParameters = {}
deviceParameters["category"] = self._category
deviceParameters["id"] = self._id
bootstrapName.append(json.dumps(deviceParameters))
bootstrapInterest = Interest(bootstrapName)
bootstrapInterest.setInterestLifetimeMilliseconds(5000)
#bootstrapKeyLocator = KeyLocator()
#bootstrapKeyLocator.setType(KeyLocatorType.KEY_LOCATOR_DIGEST)
#bootstrapKeyLocator.setKeyData(self._symKey)
#bootstrapInterest.setKeyLocator(bootstrapKeyLocator)
self._hmacHelper.signInterest(bootstrapInterest)
dump("Express bootstrap interest : ",bootstrapInterest.toUri())
self.face.expressInterest(bootstrapInterest, self.onBootstrapData, self.onTimeout)
def onInterest():
pass
def onRegisterFailed():
pass
def onBootstrapData(self, interest, data):
dump("Bootstrap data received.")
if (self._hmacHelper.verifyData(data)):
self.log.info("Bootstrap data is verified")
content = json.loads(data.getContent().toRawStr(), encoding="latin-1")
deviceNewIdentity = Name(content["deviceNewIdentity"])
controllerIdentity = Name(content["controllerIdentity"])
controllerPublicKeyInfo = content["controllerPublicKey"]
self.face.registerPrefix(content["deviceNewIdentity"],self.onInterest,self.onRegisterFailed)
#set new identity as default and generate default key-pair with KSK Certificate
self._identityStorage.addIdentity(deviceNewIdentity)
self._identityManager.setDefaultIdentity(deviceNewIdentity)
try:
self._identityManager.getDefaultKeyNameForIdentity(deviceNewIdentity)
except SecurityException:
#generate new key-pair and certificate for new identity
dump("Install new identity as default\nGenerate new key-pair and self signed certificate")
newKey = self._identityManager.generateRSAKeyPairAsDefault(Name(deviceNewIdentity), isKsk=True)
newCert = self._identityManager.selfSign(newKey)
self._identityManager.addCertificateAsIdentityDefault(newCert)
#add controller's identity and public key
keyType = controllerPublicKeyInfo["keyType"]
keyName = Name(controllerPublicKeyInfo["keyName"])
keyDer = Blob().fromRawStr(controllerPublicKeyInfo["publicKeyDer"])
dump("Controller's KeyType: ",keyType)
dump("Controller's keyName: ",keyName)
dump("Controller public key der : ",keyDer)
self._identityStorage.addIdentity(controllerIdentity)
try:
self._identityStorage.addKey(keyName, keyType, keyDer)
dump("Controller's identity, key and certificate installled.")
except SecurityException:
dump("Controller's identity, key, certificate already exists.")
#express an certificate request interest
defaultKeyName = self._identityManager.getDefaultKeyNameForIdentity(self._keyChain.getDefaultIdentity() )
self.requestCertificate(defaultKeyName)
else:
self.log.info("Bootstrap data is not verified")
def beforeLoopStart(self):
#self.face.registerPrefix('/', self.onInterest, self.onRegisterFailed)
self.expressBootstrapInterest()
def onTimeout(self, interest):
self._callbackCount += 1
dump("Time out for interest", interest.getName().toUri())
def requestCertificate(self, keyIdentity):
"""
We compose a command interest with our public key info so the controller
can sign us a certificate that can be used with other nodes in the network.
Name format : /home/<device-category>/KEY/<device-id>/<key-id>/<publickey>/ID-CERT/<version-number>
"""
certificateRequestName = self._keyChain.getDefaultIdentity()
deviceIdComponent = certificateRequestName.get(-1)
keyIdComponent = keyIdentity.get(-1)
certificateRequestName = certificateRequestName
certificateRequestName.append("KEY")
#certificateRequestName.append(deviceIdComponent)
certificateRequestName.append(keyIdComponent)
key = self._identityManager.getPublicKey(keyIdentity)
keyInfo = {}
keyInfo["keyType"] = key.getKeyType()
keyInfo["keyDer"] = key.getKeyDer().toRawStr()
certificateRequestName.append(json.dumps(keyInfo, encoding="latin-1"))
certificateRequestName.append("ID-CERT")
certificateRequest = Interest(certificateRequestName)
certificateRequest.setInterestLifetimeMilliseconds(5000)
self._hmacHelper.signInterest(certificateRequest)
dump("Sending certificate request : ",certificateRequestName)
self.face.expressInterest(certificateRequest, self.onCertificateData, self.onTimeout)
#TODO use symmetric key to sign
def onCertificateData(self, interest, data):
dump("OnCertificateData : ",data)
if __name__ == '__main__':
device = Device("tmp.conf")
device.start()