4141use  OCP \IConfig ;
4242use  OCP \ILogger ;
4343use  OCP \IUserSession ;
44+ use  OCP \Lock \ILockingProvider ;
4445
4546class  KeyManager {
4647
@@ -103,6 +104,11 @@ class KeyManager {
103104	 */ 
104105	private  $ util
105106
107+ 	/** 
108+ 	 * @var ILockingProvider 
109+ 	 */ 
110+ 	private  $ lockingProvider
111+ 
106112	/** 
107113	 * @param IStorage $keyStorage 
108114	 * @param Crypt $crypt 
@@ -119,14 +125,16 @@ public function __construct(
119125		IUserSession $ userSession
120126		Session $ session
121127		ILogger $ log
122- 		Util $ util
128+ 		Util $ util
129+ 		ILockingProvider $ lockingProvider
123130	) {
124131		$ this util  = $ util
125132		$ this session  = $ session
126133		$ this keyStorage  = $ keyStorage
127134		$ this crypt  = $ crypt
128135		$ this config  = $ config
129136		$ this log  = $ log
137+ 		$ this lockingProvider  = $ lockingProvider
130138
131139		$ this recoveryKeyId  = $ this config ->getAppValue ('encryption ' ,
132140			'recoveryKeyId ' );
@@ -161,17 +169,24 @@ public function __construct(
161169	public  function  validateShareKey () {
162170		$ shareKey$ this getPublicShareKey ();
163171		if  (empty ($ shareKey
164- 			$ keyPair$ this crypt ->createKeyPair ();
165- 
166- 			// Save public key 
167- 			$ this keyStorage ->setSystemUserKey (
168- 				$ this publicShareKeyId  . '.publicKey ' , $ keyPair'publicKey ' ],
169- 				Encryption::ID );
170- 
171- 			// Encrypt private key empty passphrase 
172- 			$ encryptedKey$ this crypt ->encryptPrivateKey ($ keyPair'privateKey ' ], '' );
173- 			$ header$ this crypt ->generateHeader ();
174- 			$ this setSystemPrivateKey ($ this publicShareKeyId , $ header$ encryptedKey
172+ 			$ this lockingProvider ->acquireLock ('encryption-generateSharedKey ' , ILockingProvider::LOCK_EXCLUSIVE , 'Encryption: shared key generation ' );
173+ 			try  {
174+ 				$ keyPair$ this crypt ->createKeyPair ();
175+ 
176+ 				// Save public key 
177+ 				$ this keyStorage ->setSystemUserKey (
178+ 					$ this publicShareKeyId  . '. '  . $ this publicKeyId , $ keyPair'publicKey ' ],
179+ 					Encryption::ID );
180+ 
181+ 				// Encrypt private key empty passphrase 
182+ 				$ encryptedKey$ this crypt ->encryptPrivateKey ($ keyPair'privateKey ' ], '' );
183+ 				$ header$ this crypt ->generateHeader ();
184+ 				$ this setSystemPrivateKey ($ this publicShareKeyId , $ header$ encryptedKey
185+ 			} catch  (\Throwable   $ e
186+ 				$ this lockingProvider ->releaseLock ('encryption-generateSharedKey ' , ILockingProvider::LOCK_EXCLUSIVE );
187+ 				throw  $ e
188+ 			}
189+ 			$ this lockingProvider ->releaseLock ('encryption-generateSharedKey ' , ILockingProvider::LOCK_EXCLUSIVE );
175190		}
176191	}
177192
@@ -184,18 +199,36 @@ public function validateMasterKey() {
184199		}
185200
186201		$ publicMasterKey$ this getPublicMasterKey ();
187- 		if  (empty ($ publicMasterKey
188- 			$ keyPair$ this crypt ->createKeyPair ();
189- 
190- 			// Save public key 
191- 			$ this keyStorage ->setSystemUserKey (
192- 				$ this masterKeyId  . '.publicKey ' , $ keyPair'publicKey ' ],
193- 				Encryption::ID );
194- 
195- 			// Encrypt private key with system password 
196- 			$ encryptedKey$ this crypt ->encryptPrivateKey ($ keyPair'privateKey ' ], $ this getMasterKeyPassword (), $ this masterKeyId );
197- 			$ header$ this crypt ->generateHeader ();
198- 			$ this setSystemPrivateKey ($ this masterKeyId , $ header$ encryptedKey
202+ 		$ privateMasterKey$ this getPrivateMasterKey ();
203+ 
204+ 		if  (empty ($ publicMasterKeyempty ($ privateMasterKey
205+ 			// There could be a race condition here if two requests would trigger 
206+ 			// the generation the second one would enter the key generation as long 
207+ 			// as the first one didn't write the key to the keystorage yet 
208+ 			$ this lockingProvider ->acquireLock ('encryption-generateMasterKey ' , ILockingProvider::LOCK_EXCLUSIVE , 'Encryption: master key generation ' );
209+ 			try  {
210+ 				$ keyPair$ this crypt ->createKeyPair ();
211+ 
212+ 				// Save public key 
213+ 				$ this keyStorage ->setSystemUserKey (
214+ 					$ this masterKeyId  . '. '  . $ this publicKeyId , $ keyPair'publicKey ' ],
215+ 					Encryption::ID );
216+ 
217+ 				// Encrypt private key with system password 
218+ 				$ encryptedKey$ this crypt ->encryptPrivateKey ($ keyPair'privateKey ' ], $ this getMasterKeyPassword (), $ this masterKeyId );
219+ 				$ header$ this crypt ->generateHeader ();
220+ 				$ this setSystemPrivateKey ($ this masterKeyId , $ header$ encryptedKey
221+ 			} catch  (\Throwable   $ e
222+ 				$ this lockingProvider ->releaseLock ('encryption-generateMasterKey ' , ILockingProvider::LOCK_EXCLUSIVE );
223+ 				throw  $ e
224+ 			}
225+ 			$ this lockingProvider ->releaseLock ('encryption-generateMasterKey ' , ILockingProvider::LOCK_EXCLUSIVE );
226+ 		} elseif  (empty ($ publicMasterKey
227+ 			$ this log ->error ('A private master key is available but the public key could not be found. This should never happen. ' );
228+ 			return ;
229+ 		} elseif  (empty ($ privateMasterKey
230+ 			$ this log ->error ('A public master key is available but the private key could not be found. This should never happen. ' );
231+ 			return ;
199232		}
200233
201234		if  (!$ this session ->isPrivateKeySet ()) {
@@ -222,7 +255,7 @@ public function recoveryKeyExists() {
222255	 * @return string 
223256	 */ 
224257	public  function  getRecoveryKey () {
225- 		return  $ this keyStorage ->getSystemUserKey ($ this recoveryKeyId  . '.publicKey  '  , Encryption::ID );
258+ 		return  $ this keyStorage ->getSystemUserKey ($ this recoveryKeyId  . '. '   .  $ this -> publicKeyId , Encryption::ID );
226259	}
227260
228261	/** 
@@ -239,7 +272,7 @@ public function getRecoveryKeyId() {
239272	 * @return bool 
240273	 */ 
241274	public  function  checkRecoveryPassword ($ password
242- 		$ recoveryKey$ this keyStorage ->getSystemUserKey ($ this recoveryKeyId  . '.privateKey  '  , Encryption::ID );
275+ 		$ recoveryKey$ this keyStorage ->getSystemUserKey ($ this recoveryKeyId  . '. '   .  $ this -> privateKeyId , Encryption::ID );
243276		$ decryptedRecoveryKey$ this crypt ->decryptPrivateKey ($ recoveryKey$ password
244277
245278		if  ($ decryptedRecoveryKey
@@ -251,7 +284,7 @@ public function checkRecoveryPassword($password) {
251284	/** 
252285	 * @param string $uid 
253286	 * @param string $password 
254- 	 * @param string  $keyPair 
287+ 	 * @param array  $keyPair 
255288	 * @return bool 
256289	 */ 
257290	public  function  storeKeyPair ($ uid$ password$ keyPair
@@ -277,7 +310,7 @@ public function storeKeyPair($uid, $password, $keyPair) {
277310	public  function  setRecoveryKey ($ password$ keyPair
278311		// Save Public Key 
279312		$ this keyStorage ->setSystemUserKey ($ this getRecoveryKeyId ().
280- 			'.publicKey  '  ,
313+ 			'. '   .  $ this -> publicKeyId ,
281314			$ keyPair'publicKey ' ],
282315			Encryption::ID );
283316
@@ -435,7 +468,7 @@ public function getFileKey($path, $uid) {
435468			// use public share key for public links 
436469			$ uid$ this getPublicShareKeyId ();
437470			$ shareKey$ this getShareKey ($ path$ uid
438- 			$ privateKey$ this keyStorage ->getSystemUserKey ($ this publicShareKeyId  . '.privateKey  '  , Encryption::ID );
471+ 			$ privateKey$ this keyStorage ->getSystemUserKey ($ this publicShareKeyId  . '. '   .  $ this -> privateKeyId , Encryption::ID );
439472			$ privateKey$ this crypt ->decryptPrivateKey ($ privateKey
440473		} else  {
441474			$ shareKey$ this getShareKey ($ path$ uid
@@ -578,7 +611,7 @@ public function getPublicShareKeyId() {
578611	 * @return string 
579612	 */ 
580613	public  function  getPublicShareKey () {
581- 		return  $ this keyStorage ->getSystemUserKey ($ this publicShareKeyId  . '.publicKey  '  , Encryption::ID );
614+ 		return  $ this keyStorage ->getSystemUserKey ($ this publicShareKeyId  . '. '   .  $ this -> publicKeyId , Encryption::ID );
582615	}
583616
584617	/** 
@@ -718,6 +751,15 @@ public function getMasterKeyId() {
718751	 * @return string 
719752	 */ 
720753	public  function  getPublicMasterKey () {
721- 		return  $ this keyStorage ->getSystemUserKey ($ this masterKeyId  . '.publicKey ' , Encryption::ID );
754+ 		return  $ this keyStorage ->getSystemUserKey ($ this masterKeyId  . '. '  . $ this publicKeyId , Encryption::ID );
755+ 	}
756+ 
757+ 	/** 
758+ 	 * get public master key 
759+ 	 * 
760+ 	 * @return string 
761+ 	 */ 
762+ 	public  function  getPrivateMasterKey () {
763+ 		return  $ this keyStorage ->getSystemUserKey ($ this masterKeyId  . '. '  . $ this privateKeyId , Encryption::ID );
722764	}
723765}
0 commit comments