2 * Copyright 2012, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
19 Keyring::Keyring(const char* name
)
35 Keyring::ReadFromMessage(const BMessage
& message
)
37 status_t result
= message
.FindString("name", &fName
);
41 result
= message
.FindBool("hasUnlockKey", &fHasUnlockKey
);
45 if (message
.GetBool("noData", false)) {
46 fFlatBuffer
.SetSize(0);
52 result
= message
.FindData("data", B_RAW_TYPE
, &data
, &size
);
59 fFlatBuffer
.SetSize(0);
60 ssize_t written
= fFlatBuffer
.WriteAt(0, data
, size
);
61 if (written
!= size
) {
62 fFlatBuffer
.SetSize(0);
63 return written
< 0 ? written
: B_ERROR
;
71 Keyring::WriteToMessage(BMessage
& message
)
73 status_t result
= _EncryptToFlatBuffer();
77 if (fFlatBuffer
.BufferLength() == 0)
78 result
= message
.AddBool("noData", true);
80 result
= message
.AddData("data", B_RAW_TYPE
, fFlatBuffer
.Buffer(),
81 fFlatBuffer
.BufferLength());
86 result
= message
.AddBool("hasUnlockKey", fHasUnlockKey
);
90 return message
.AddString("name", fName
);
95 Keyring::Unlock(const BMessage
* keyMessage
)
100 if (fHasUnlockKey
== (keyMessage
== NULL
))
103 if (keyMessage
!= NULL
)
104 fUnlockKey
= *keyMessage
;
106 status_t result
= _DecryptFromFlatBuffer();
107 if (result
!= B_OK
) {
108 fUnlockKey
.MakeEmpty();
123 _EncryptToFlatBuffer();
125 fUnlockKey
.MakeEmpty();
127 fApplications
.MakeEmpty();
133 Keyring::IsUnlocked() const
140 Keyring::HasUnlockKey() const
142 return fHasUnlockKey
;
147 Keyring::UnlockKey() const
154 Keyring::SetUnlockKey(const BMessage
& keyMessage
)
157 return B_NOT_ALLOWED
;
159 fHasUnlockKey
= true;
160 fUnlockKey
= keyMessage
;
167 Keyring::RemoveUnlockKey()
170 return B_NOT_ALLOWED
;
172 fUnlockKey
.MakeEmpty();
173 fHasUnlockKey
= false;
180 Keyring::GetNextApplication(uint32
& cookie
, BString
& signature
,
184 return B_NOT_ALLOWED
;
186 char* nameFound
= NULL
;
187 status_t result
= fApplications
.GetInfo(B_MESSAGE_TYPE
, cookie
++,
190 return B_ENTRY_NOT_FOUND
;
193 result
= fApplications
.FindMessage(nameFound
, &appMessage
);
195 return B_ENTRY_NOT_FOUND
;
197 result
= appMessage
.FindString("path", &path
);
201 signature
= nameFound
;
207 Keyring::FindApplication(const char* signature
, const char* path
,
208 BMessage
& appMessage
)
211 return B_NOT_ALLOWED
;
215 if (fApplications
.GetInfo(signature
, &type
, &count
) != B_OK
)
216 return B_ENTRY_NOT_FOUND
;
218 for (int32 i
= 0; i
< count
; i
++) {
219 if (fApplications
.FindMessage(signature
, i
, &appMessage
) != B_OK
)
223 if (appMessage
.FindString("path", &appPath
) != B_OK
)
230 appMessage
.MakeEmpty();
231 return B_ENTRY_NOT_FOUND
;
236 Keyring::AddApplication(const char* signature
, const BMessage
& appMessage
)
239 return B_NOT_ALLOWED
;
241 status_t result
= fApplications
.AddMessage(signature
, &appMessage
);
251 Keyring::RemoveApplication(const char* signature
, const char* path
)
254 return B_NOT_ALLOWED
;
257 // We want all of the entries for this signature removed.
258 status_t result
= fApplications
.RemoveName(signature
);
260 return B_ENTRY_NOT_FOUND
;
268 if (fApplications
.GetInfo(signature
, &type
, &count
) != B_OK
)
269 return B_ENTRY_NOT_FOUND
;
271 for (int32 i
= 0; i
< count
; i
++) {
273 if (fApplications
.FindMessage(signature
, i
, &appMessage
) != B_OK
)
277 if (appMessage
.FindString("path", &appPath
) != B_OK
)
280 if (appPath
== path
) {
281 fApplications
.RemoveData(signature
, i
);
287 return B_ENTRY_NOT_FOUND
;
292 Keyring::FindKey(const BString
& identifier
, const BString
& secondaryIdentifier
,
293 bool secondaryIdentifierOptional
, BMessage
* _foundKeyMessage
) const
296 return B_NOT_ALLOWED
;
300 if (fData
.GetInfo(identifier
, &type
, &count
) != B_OK
)
301 return B_ENTRY_NOT_FOUND
;
303 // We have a matching primary identifier, need to check for the secondary
305 for (int32 i
= 0; i
< count
; i
++) {
307 if (fData
.FindMessage(identifier
, i
, &candidate
) != B_OK
)
310 BString candidateIdentifier
;
311 if (candidate
.FindString("secondaryIdentifier",
312 &candidateIdentifier
) != B_OK
) {
313 candidateIdentifier
= "";
316 if (candidateIdentifier
== secondaryIdentifier
) {
317 if (_foundKeyMessage
!= NULL
)
318 *_foundKeyMessage
= candidate
;
323 // We didn't find an exact match.
324 if (secondaryIdentifierOptional
) {
325 if (_foundKeyMessage
== NULL
)
328 // The secondary identifier is optional, so we just return the
330 return fData
.FindMessage(identifier
, 0, _foundKeyMessage
);
333 return B_ENTRY_NOT_FOUND
;
338 Keyring::FindKey(BKeyType type
, BKeyPurpose purpose
, uint32 index
,
339 BMessage
& _foundKeyMessage
) const
342 return B_NOT_ALLOWED
;
344 for (int32 keyIndex
= 0;; keyIndex
++) {
346 char* identifier
= NULL
;
347 if (fData
.GetInfo(B_MESSAGE_TYPE
, keyIndex
, &identifier
, NULL
,
352 if (type
== B_KEY_TYPE_ANY
&& purpose
== B_KEY_PURPOSE_ANY
) {
353 // No need to inspect the actual keys.
354 if ((int32
)index
>= count
) {
359 return fData
.FindMessage(identifier
, index
, &_foundKeyMessage
);
362 // Go through the keys to check their type and purpose.
363 for (int32 subkeyIndex
= 0; subkeyIndex
< count
; subkeyIndex
++) {
365 if (fData
.FindMessage(identifier
, subkeyIndex
, &subkey
) != B_OK
)
369 if (type
!= B_KEY_TYPE_ANY
) {
371 if (subkey
.FindUInt32("type", (uint32
*)&subkeyType
) != B_OK
)
374 match
= subkeyType
== type
;
377 if (match
&& purpose
!= B_KEY_PURPOSE_ANY
) {
378 BKeyPurpose subkeyPurpose
;
379 if (subkey
.FindUInt32("purpose", (uint32
*)&subkeyPurpose
)
384 match
= subkeyPurpose
== purpose
;
389 _foundKeyMessage
= subkey
;
398 return B_ENTRY_NOT_FOUND
;
403 Keyring::AddKey(const BString
& identifier
, const BString
& secondaryIdentifier
,
404 const BMessage
& keyMessage
)
407 return B_NOT_ALLOWED
;
409 // Check for collisions.
410 if (FindKey(identifier
, secondaryIdentifier
, false, NULL
) == B_OK
)
411 return B_NAME_IN_USE
;
413 // We're fine, just add the new key.
414 status_t result
= fData
.AddMessage(identifier
, &keyMessage
);
424 Keyring::RemoveKey(const BString
& identifier
,
425 const BMessage
& keyMessage
)
428 return B_NOT_ALLOWED
;
432 if (fData
.GetInfo(identifier
, &type
, &count
) != B_OK
)
433 return B_ENTRY_NOT_FOUND
;
435 for (int32 i
= 0; i
< count
; i
++) {
437 if (fData
.FindMessage(identifier
, i
, &candidate
) != B_OK
)
440 // We require an exact match.
441 if (!candidate
.HasSameData(keyMessage
))
444 status_t result
= fData
.RemoveData(identifier
, i
);
452 return B_ENTRY_NOT_FOUND
;
457 Keyring::Compare(const Keyring
* one
, const Keyring
* two
)
459 return strcmp(one
->Name(), two
->Name());
464 Keyring::Compare(const BString
* name
, const Keyring
* keyring
)
466 return strcmp(name
->String(), keyring
->Name());
471 Keyring::_EncryptToFlatBuffer()
477 return B_NOT_ALLOWED
;
480 status_t result
= container
.AddMessage("data", &fData
);
484 result
= container
.AddMessage("applications", &fApplications
);
488 fFlatBuffer
.SetSize(0);
489 fFlatBuffer
.Seek(0, SEEK_SET
);
491 result
= container
.Flatten(&fFlatBuffer
);
496 // TODO: Actually encrypt the flat buffer...
505 Keyring::_DecryptFromFlatBuffer()
507 if (fFlatBuffer
.BufferLength() == 0)
511 // TODO: Actually decrypt the flat buffer...
515 fFlatBuffer
.Seek(0, SEEK_SET
);
516 status_t result
= container
.Unflatten(&fFlatBuffer
);
520 result
= container
.FindMessage("data", &fData
);
524 result
= container
.FindMessage("applications", &fApplications
);
525 if (result
!= B_OK
) {